Algorithm

백준 17141번 연구소2

이무쿤 2020. 7. 18. 11:17
반응형

문제

인체에 치명적인 바이러스를 연구하던 연구소에 승원이가 침입했고, 바이러스를 유출하려고 한다. 승원이는 연구소의 특정 위치에 바이러스 M개를 놓을 것이고, 승원이의 신호와 동시에 바이러스는 퍼지게 된다.

연구소는 크기가 N×N인 정사각형으로 나타낼 수 있으며, 정사각형은 1×1 크기의 정사각형으로 나누어져 있다. 연구소는 빈 칸, 벽으로 이루어져 있으며, 벽은 칸 하나를 가득 차지한다.

일부 빈 칸은 바이러스를 놓을 수 있는 칸이다. 바이러스는 상하좌우로 인접한 모든 빈 칸으로 동시에 복제되며, 1초가 걸린다.

예를 들어, 아래와 같이 연구소가 생긴 경우를 살펴보자. 0은 빈 칸, 1은 벽, 2는 바이러스를 놓을 수 있는 칸이다.

2 0 0 0 1 1 0 0 0 1 0 1 2 0 0 1 1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 2 0 1 1 0 1 0 0 0 0 0 2 1 0 0 0 0 2

M = 3이고, 바이러스를 아래와 같이 놓은 경우 6초면 모든 칸에 바이러스를 퍼뜨릴 수 있다. 벽은 -, 바이러스를 놓은 위치는 0, 빈 칸은 바이러스가 퍼지는 시간으로 표시했다.

6 6 5 4 - - 2 5 6 - 3 - 0 1 4 - - 2 - 1 2 3 - 2 1 2 2 3 2 2 1 0 1 - - 1 - 2 1 2 3 4 0 - 3 2 3 4 5

시간이 최소가 되는 방법은 아래와 같고, 5초만에 모든 칸에 바이러스를 퍼뜨릴 수 있다.

0 1 2 3 - - 2 1 2 - 3 - 0 1 2 - - 2 - 1 2 3 - 2 1 2 2 3 3 2 1 0 1 - - 4 - 2 1 2 3 4 5 - 3 2 3 4 5

연구소의 상태가 주어졌을 때, 모든 빈 칸에 바이러스를 퍼뜨리는 최소 시간을 구해보자.

입력

첫째 줄에 연구소의 크기 N(5 ≤ N ≤ 50), 놓을 수 있는 바이러스의 개수 M(1 ≤ M ≤ 10)이 주어진다.

둘째 줄부터 N개의 줄에 연구소의 상태가 주어진다. 0은 빈 칸, 1은 벽, 2는 바이러스를 놓을 수 있는 칸이다. 2의 개수는 M보다 크거나 같고, 10보다 작거나 같은 자연수이다.

출력

연구소의 모든 빈 칸에 바이러스가 있게 되는 최소 시간을 출력한다. 바이러스를 어떻게 놓아도 모든 빈 칸에 바이러스를 퍼뜨릴 수 없는 경우에는 -1을 출력한다.

 

DFS + BFS로 쉽게 풀 수 있는 문제지만, 빈 공간이 없는 경우 0을 출력해야 하는데 도달 불가로 -1을 출력하는

예외만 처리해주면 된다.

#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<string.h>
#include<map>
using namespace std;


int N, M;
int arr[50][50];
vector<pair<int, int> > virus;

int dy[4] = { -1,1,0,0 };
int dx[4] = { 0,0,-1,1 };

bool flag = false;
int mina = 987654321;

void DFS(int idx, int cur)
{
	if (cur == M)
	{
		queue<pair<pair<int, int >,int> > que;
		int temp[50][50];
		int C = 0;
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < N; j++)
			{
				if (arr[i][j] == 2)
				{
					que.push({ {i,j },0 });
				}
				else if (!arr[i][j])
				{
					C++;
				}
				temp[i][j] = arr[i][j];
			}
		}
		if (C == 0)
		{
			flag = true;
			mina = 0;
			return;
		}

		int count = 0;
		while (!que.empty())
		{
			int y = que.front().first.first;
			int x = que.front().first.second;
			int cost = que.front().second;
			que.pop();

			

			for (int i = 0; i < 4; i++)
			{
				int newy = y + dy[i];
				int newx = x + dx[i];
				if (newy >= 0 && newy < N && newx >= 0 && newx < N)
				{
					if (!temp[newy][newx])
					{
						temp[newy][newx] = 2;
						que.push({ {newy,newx},cost + 1 });
						count++;
						if (count == C)
						{
							flag = true;
							if (mina > cost + 1)
							{
								mina = cost + 1;
							}
							return;
						}
					}
				}
			}
		}

		return;
	}


	for (int i = idx + 1; i < virus.size(); i++)
	{
		arr[virus[i].first][virus[i].second] = 2;
		DFS(i, cur + 1);
		arr[virus[i].first][virus[i].second] = 0;
	}
}

int main(void)
{
	cin >> N >> M;


	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			cin >> arr[i][j];
			if (arr[i][j] == 2)
			{
				virus.push_back({ i,j });
				arr[i][j] = 0;
			}
		}
	}

	for (int i = 0; i < virus.size(); i++)
	{
		arr[virus[i].first][virus[i].second] = 2;
		DFS(i, 1);
		arr[virus[i].first][virus[i].second] = 0;
	}

	if (!flag)
	{
		cout << -1 << endl;
	}
	else
	{
		cout << mina << endl;
	}
	
}
반응형