ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • C++ ) 백준 3055 탈출
    알고리즘과 언어/c++ 2022. 2. 16. 19:04

     

     

     

    문제)

     

    https://www.acmicpc.net/problem/3055

     

    3055번: 탈출

    사악한 암흑의 군주 이민혁은 드디어 마법 구슬을 손에 넣었고, 그 능력을 실험해보기 위해 근처의 티떱숲에 홍수를 일으키려고 한다. 이 숲에는 고슴도치가 한 마리 살고 있다. 고슴도치는 제

    www.acmicpc.net

     

     

    BFS가 같은 맵에서 2번 진행되어야 하는 문제다.

     

    1. 젖은 물의 공간이 확장되며 (BFS)

    2. 고슴도치의 최소 거리를 구해야 한다. (BFS)

     

     

    구현 자체는 어렵지 않으나 3가지를 어떻게 해결할 것인지가 관건일 것 같다.

     

    1. 고슴도치는 물에 젖게 될 곳에도 가면 안된다.

     

    -> 젖은 물의 공간을 먼저 확장하고, 그 다음으로 고슴도치의 BFS를 진행함으로써 해결했다.

     

    2. 서로 다른 지점에서의 BFS 두 가지를 진행하는 방법?

     

    -> 한 지점에서의 BFS는 while 문을 통해서 queue가 empty가 될 때 까지 진행한다.

    하지만 두 가지를 한꺼번에 하기위해서는 queue가 empty가 될 떄 까지 계속 진행되는 것이 아닌(물이 전체적으로 확장되는 것이 아닌), 물이 1번 확장되고 고슴도치가 갈 수 있는 길이 1번 확장되고를 번갈아 해야한다.

     

    이 문제를 해결하기 위해서는 각각의 확장을 진행하기 전에 queue의 size를 구해서,

    물이 1번 확장이 되고 queue에 담긴 나머지는 다음에 확장이 되도록 (고슴도치가 1번 확장이 된 후에) 큐에 남겨놓는 방법이다.

    즉, bfs 전에 queue의 길이를 구해서 bfs가 한 칸씩만 확장되도록 한다.

     

    3. 1번씩 확장하는 것을 반복할 때 탈출 조건

     

    -> 고슴도치가 무사히 목적지에 도착했으면 값을 'W(in)'으로 바꾸도록 설정했다.

    탈출 조건은 목적지가 D에서 W로 바뀌었거나, 고슴도치가 더 이상 갈 곳이 없을 때(Move.empty()) 탈출문을 나오도록 설정했다.

     

    #include <iostream>
    #include <queue>
    
    using namespace std;
    
    char map[50][50];
    int Fcheckmap[50][50]; // 물의 방문 체크
    int Mcheckmap[50][50]; // 고슴도치의 방문 체크
    
    int dy[] = {0, 0, -1, 1};
    int dx[] = {-1, 1, 0, 0};
    
    int R, C;
    int yy, xx; // D(목적지)의 y좌표, x좌표를 담을 곳
    int Count = 0;
    
    
    void Solve(queue <pair<int, int>> & Move , queue <pair<int, int>> & Flood){
    
    	int Movesize;
    	int Floodsize;
    	int tmpy;
    	int tmpx;
    	pair<int, int> tmp;
    
    	//cout << "flood" << endl;
    	while (map[yy][xx] != 'W' && !Move.empty()) {
    
    		//cout << "count is " << Count << endl;
    
    		Movesize = Move.size(); // 미리 queue의 길이를 세어 길이 1만큼만 확장하도록
    		Floodsize = Flood.size(); //미리 queue의 길이를 세어 길이 1만큼만 물에 젖도록
    
    		while (!Flood.empty() && Floodsize)
    		{
    			Floodsize--;
    			tmp = Flood.front();
    			Flood.pop();
    			for(int i = 0; i < 4; i++)
    			{
    				tmpy = tmp.first + dy[i];
    				tmpx = tmp.second + dx[i];
    
    				if (tmpy < 0 || tmpy >= R || tmpx < 0 || tmpx >= C || map[tmpy][tmpx] == 'X' || Fcheckmap[tmpy][tmpx] || map[tmpy][tmpx] == 'D')
    					continue; // 맵을 넘어가거나, 돌을 만나거나, 이미 방문했거나, 목적지라면 진행하지 않는다.
    //				cout << tmpy << " " << tmpx << endl;
    				map[tmpy][tmpx] = '*'; // 물에 젖음을 미리 표시 (여기에는 가지 않게)
    				Flood.push(make_pair(tmpy, tmpx)); // queue에 넣어준다.
    				Fcheckmap[tmpy][tmpx] = 1; // 방문 표시한다.
    			}
    		}
    
    		//cout << "move" << endl;
    		while (!Move.empty() && Movesize)
    		{
    			Movesize--;
    			tmp = Move.front();
    			Move.pop();
    			for(int i = 0; i < 4; i++)
    			{
    				tmpy = tmp.first + dy[i];
    				tmpx = tmp.second + dx[i];
    
    				if (tmpy < 0 || tmpy >= R || tmpx < 0 || tmpx >= C || map[tmpy][tmpx] == 'X' || map[tmpy][tmpx] == '*' || Mcheckmap[tmpy][tmpx])
    					continue; // 맵을 넘어가거나, 돌을 만나거나, 물이 있거나, 이미 방문했다면 진행하지 않는다.
    
    				//cout << tmpy << " " << tmpx << endl;
    
    				if (map[tmpy][tmpx] == 'D')
    					map[tmpy][tmpx] = 'W'; // 목적지에 도착했다면 'W'로 바꿔주어 탈출 조건을 만들어준다.
    				Move.push(make_pair(tmpy, tmpx));
    				Mcheckmap[tmpy][tmpx] = 1;
    			}
    		}
    		Count++; // 몇 번 만에 목적지에 도착했는지 센다.
    	}
    
    	if (map[yy][xx] == 'W')
    		cout << Count;
    	else
    		cout << "KAKTUS";
    
    }
    int main() {
    
    	cin >> R >> C;
    
    	queue <pair<int, int>> Move;
    	queue <pair<int, int>> Flood;
    
    	char tmp;
    
    
    	for(int i = 0; i <R; i++)
    	{
    		for(int j = 0; j < C; j++)
    		{
    
    			cin >> tmp;
    			if (tmp == 'S') {
    				Move.push(make_pair(i, j)); // 고슴도치 좌표 queue에 넣기
    				Mcheckmap[i][j] = 1;
    			}
    			if (tmp == '*') {
    				Flood.push(make_pair(i, j)); // 젖은 지역 queue에 넣기
    				Fcheckmap[i][j] = 1;
    			}
    			if (tmp == 'D')
    			{
    				yy = i;
    				xx = j;
    			}
    			map[i][j] = tmp;
    		}
    	}
    
    	Solve(Move, Flood);
    }
Designed by Tistory.