본문 바로가기

ps(알고리즘)

백조의 호수

 

문제를 보고 떠올린 해결책은 큐와 유니온파인드를 이용한 방식이다.

일단 처음에 물을 큐에 담고 큐에서 하나씩 꺼내 보면서 상하좌우 네 방향에서 만약 물이면 유니온파인드로 합쳐주고,

얼음이면 물로 바꾸고 큐에 날짜 정보를 포함시켜 담아준다.

백조 두개의 유니온파인드 그룹이 같을 때까지 반복하면 되고, 모든 점은 한번씩만 큐에 저장되도록 하면

최대 1500*1500만큼만 반복하면 되서 시간 안에 해결할 수 있다.

근데 그렇게 코드를 짜고 예제까지 통과했는데 메모리 초과로 풀 수 없었다.

맵에 대한 정보 1500*1500짜리 배열 말고도 유니온 파인드를 위한 1500*1500 배열이 하나 더 필요한데

설마 1500*1500 배열 2개로 터질줄은 몰랐다.

 

어떻게 해야 할지 모르겠어서 그냥 찾아봤는데 놀랍게도 그냥 백조를 계속 bfs해주는 간단한 방식으로 풀린다.

백조의 위치에서부터 갈 수 있는곳을 bfs해주고 물들도 bfs해주면서 얼음을 녹이고, 얼음이 녹았으면 또 bfs해주면서

백조 둘이 만날 때까지 반복하면 된다.

이렇게 하면 시간이 안될거라고 생각했는데 된다.

/*
#include<stdio.h>
#include<stack>
#include<queue>
using namespace std;
int R,C;
int parent[1504][1504];
int maps[1504][1504];
int firstx,firsty,secondx,secondy;
int ans;
struct Data{
    int day,x,y;
    bool operator<(const Data R)const{
        return day>R.day;
    }
};
priority_queue<Data>swan;
int finds(int ax,int ay)
{
    if(ax*C+ay==parent[ax][ay]) return ax*C+ay;
    else{
        return parent[ax][ay]=finds(parent[ax][ay]/C,parent[ax][ay]%C);
    }
}
void unions(int ax,int ay,int bx,int by)
{
    if(finds(ax,ay)!=finds(bx,by))
    {
        parent[finds(ax,ay)/C][finds(ax,ay)%C]=finds(bx,by);
    }
    return;
}
int main()
{
    scanf("%d %d",&R,&C);
    firstx=-1;
    for(int i=0;i<R;i++)
    {
        char x[1504];
        scanf("%s",x);
        for(int j=0;j<C;j++)
        {
            if(x[j]=='.')
            {
                maps[i][j]=0;
                swan.push({0,i,j});
            }
            else if(x[j]=='X')
            {
                maps[i][j]=1;
            }
            else if(x[j]=='L')
            {
                if(firstx==-1){
                    firstx=i;
                    firsty=j;
                }
                else{
                    secondx=i;
                    secondy=j;
                }
                maps[i][j]=0;
                swan.push({0,i,j});
            }
        }
    }
    for(int i=0;i<R;i++)
    {
        for(int j=0;j<C;j++)
        {
            parent[i][j]=i*C+j;
        }
    }
    while(finds(firstx,firsty)!=finds(secondx,secondy))
    {
        Data t = swan.top();
        swan.pop();
        maps[t.x][t.y]=0;
        int wx[4]={0,0,1,-1};
        int wy[4]={1,-1,0,0};
        for(int i=0;i<4;i++)
        {
            if(t.x+wx[i]>=R || t.x+wx[i]<0 || t.y+wy[i]>=C || t.y+wy[i]<0) continue;
            if(maps[t.x+wx[i]][t.y+wy[i]]==0) unions(t.x,t.y,t.x+wx[i],t.y+wy[i]);
            if(maps[t.x+wx[i]][t.y+wy[i]]==1){
                swan.push({t.day+1,t.x+wx[i],t.y+wy[i]});
            }
        }
        if(finds(firstx,firsty)==finds(secondx,secondy))
        {
            ans=t.day;
        }
    }
    printf("%d",ans);
}
*/
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
#include<stdio.h>
using namespace std;
int R, C;
vector<string> arr;
bool isFind = false;
pair<int, int> swan;
queue<pair<int, int>> sq, wq, tmpSQ, tmpWQ;
int dy[4][2] = { {-1,0}, {1,0}, {0,-1}, {0,1} };
bool ch[1501][1501];
void swanBFS() {
	while (!sq.empty()) {
		int x = sq.front().first;
		int y = sq.front().second;
		sq.pop();
		for (int k = 0; k < 4; k++) {
			int nx = x + dy[k][0];
			int ny = y + dy[k][1];
			if (nx < 0 || ny < 0 || nx >= R || ny >= C || ch[nx][ny]) continue;
			ch[nx][ny] = true;
			if (arr[nx][ny] == 'X') tmpSQ.push({ nx,ny });
			else if (arr[nx][ny] == '.') sq.push({ nx,ny });
			else if (arr[nx][ny] == 'L') {
				isFind = true;
				break;
			}
		}
	}
}

void waterBFS() {
	while (!wq.empty()) {
		int x = wq.front().first;
		int y = wq.front().second;
		wq.pop();
		for (int k = 0; k < 4; k++) {
			int nx = x + dy[k][0];
			int ny = y + dy[k][1];
			if (nx < 0 || ny < 0 || nx >= R || ny >= C) continue;
			if (arr[nx][ny] == 'X') {
				arr[nx][ny] = '.';
				tmpWQ.push({ nx,ny });
			}
		}
	}
}

int meetDay() {
	int day = 0;
	while (!isFind) {
		swanBFS();
		if (isFind) break;
		waterBFS();
		sq = tmpSQ;
		wq = tmpWQ;
		while (!tmpSQ.empty()) tmpSQ.pop();
		while (!tmpWQ.empty()) tmpWQ.pop();
		day++;
	}

	return day;
}

int main() {
	scanf("%d %d",&R,&C);
	for (int i = 0; i < R; i++) {
		string str;
		cin >> str;
		arr.push_back(str);
	}
	for (int i = 0; i < R; i++) {
		for (int j = 0; j < arr[i].size(); j++) {
			if (arr[i][j] == 'L') {
				swan.first = i;
				swan.second = j;
			}
			if (arr[i][j] != 'X') {
				wq.push({ i,j });
			}
		}
	}
	ch[swan.first][swan.second] = true;
	sq.push(swan);
	printf("%d",meetDay());
}

주석처리된 부분은 처음에 생각한 풀이이다.

이론상 시간이 더 빠른데 메모리 때문에 실패한 풀이라서 아까워서 넣었다.

'ps(알고리즘)' 카테고리의 다른 글

볼록 껍질  (0) 2024.12.03
Strongly Connected Componen  (0) 2024.12.03
책 페이지  (1) 2024.11.26
오아시스 재결합  (0) 2024.11.26
LCA 2  (0) 2024.11.11