2 분 소요

불! (백준 Gold 3)

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

미로에서 불이 났을때 탈출할 수 있는지
탈출 가능하다면 그 최단 시간을 구하는 문제

  • 사람과 불은 상하좌우로 이동 가능 (시간당 1칸)
    (다만 벽을 통과할 순 없음)
  • 사람은 1명만 주어지며, 불보다 먼저 이동
  • 가장 끝 칸에서, 한번 더 움직여야 탈출 가능
  • 불은 매시간마다 상하좌우로 ‘확산’

풀이 방법

BFS 문제

  • 각 시간을 ‘지정’해야 하기에
    큐에 집어넣는 순서를 까다롭게 지정해야 함
    플레이어 -> 4방향 검사 후 Push
    불 -> 4방향 검사 후 Push
    이 순서대로 진행시, 플레이어가 불보다 먼저 움직일 수 있음
    (또한 다시 플레이어로 넘어온 시점이 곧 1 시간의 증가)

  • 플레이어가 ‘끝’칸에 도달하더라도 그 칸이 이미
    ‘불’이 붙어 있다면 실패이므로
    ‘도착 시점’에서 한번 더 검사
    (끝칸에서 바로 탈출하면 불이 그것을 막는 경우의 수를 놓침)

제출 코드

#include<iostream>
#include<vector>
#include<queue>
#include<string>

using namespace std;

const int dirY[4] = { 0,-1,0,1 };
const int dirX[4] = { -1,0,1,0 };

int r,c;

struct infos
{
	int y, x;
	int cost;
	bool bPlayer;
};

int bfs(vector<string>& maps,const pair<int,int>& start,const vector<pair<int,int>> fires)
{
	vector<vector<bool>> visit(r, vector<bool>(c, false));
	queue<infos> pq;
	pq.push({ start.first,start.second,0,true });

	for (const auto& f : fires)
	{
		pq.push({ f.first,f.second,-1,false });
	}

	while (pq.empty() == false)
	{
		int nowy = pq.front().y;
		int nowx = pq.front().x;
		int nowcost = pq.front().cost;
		bool isPlayer = pq.front().bPlayer;
		pq.pop();

		if (isPlayer)
		{
			if (nowy < 0 ||
				nowy > r - 1 ||
				nowx < 0 ||
				nowx > c - 1)
			{
				return nowcost;
			}

			if (maps[nowy][nowx] == 'F')
				continue;

			for (int i = 0; i < 4; i++)
			{
				int ny = nowy + dirY[i];
				int nx = nowx + dirX[i];

				if (ny < 0 || ny >= r ||
					nx < 0 || nx >= c)
				{
					pq.push({ ny,nx,nowcost + 1,true }); // 탈출 조건
					continue;
				}

				if (maps[ny][nx] == '#' || maps[ny][nx] == 'F')
					continue;
				
				if (visit[ny][nx])
					continue;

				visit[ny][nx] = true;
				pq.push({ ny,nx,nowcost + 1,true });
			}
		}
		else
		{
			for (int i = 0; i < 4; i++)
			{
				int ny = nowy + dirY[i];
				int nx = nowx + dirX[i];

				if (ny < 0 || ny >= r ||
					nx < 0 || nx >= c)
					continue;

				if (maps[ny][nx] == '#' || maps[ny][nx] == 'F')
					continue;

				maps[ny][nx] = 'F';
				pq.push({ ny,nx,nowcost + 1,false });
			}
		}

	}

	return -1;
}

int main()
{
	cin >> r >> c;

	vector<string> maps(r);

	pair<int, int> start;
	vector<pair<int, int>> fires;

	for (int i = 0; i < r; i++)
	{
		cin >> maps[i];
		for (int j = 0; j < c; j++)
		{
			if (maps[i][j] == 'J')
			{
				start.first = i;
				start.second = j;
			}
			else if (maps[i][j] == 'F')
			{
				fires.push_back({ i,j });
			}
		}
	}

	int v = bfs(maps, start, fires);
	if (v == -1)
		cout << "IMPOSSIBLE";
	else
		cout << v;

	return 0;
}

결과

Image

BFS 중에서 ‘다른 동적 요소’를 집어넣고
같이 BFS를 돌리는 재미있는 문제였다

  • 원래는 더 높은 난이도의 문제에 도전해보려 하였으나
    현재는 Gold의 문제들을 푸는데 먼저 익숙해질 필요가 있어보인다
    (골드 난이도 1,2를 1시간 내로 풀 정도)

댓글남기기