Algorithm

백준 14502번 연구소 (삼성 기출)

이무쿤 2020. 1. 11. 14:22
반응형

문제

인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다.

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

일부 칸은 바이러스가 존재하며, 이 바이러스는 상하좌우로 인접한 빈 칸으로 모두 퍼져나갈 수 있다. 새로 세울 수 있는 벽의 개수는 3개이며, 꼭 3개를 세워야 한다.

예를 들어, 아래와 같이 연구소가 생긴 경우를 살펴보자.

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 0 0 1 1 0 1 0 0 0 0 0 0 1 0 0 0 0 0

이때, 0은 빈 칸, 1은 벽, 2는 바이러스가 있는 곳이다. 아무런 벽을 세우지 않는다면, 바이러스는 모든 빈 칸으로 퍼져나갈 수 있다.

2행 1열, 1행 2열, 4행 6열에 벽을 세운다면 지도의 모양은 아래와 같아지게 된다.

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

바이러스가 퍼진 뒤의 모습은 아래와 같아진다.

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

벽을 3개 세운 뒤, 바이러스가 퍼질 수 없는 곳을 안전 영역이라고 한다. 위의 지도에서 안전 영역의 크기는 27이다.

연구소의 지도가 주어졌을 때 얻을 수 있는 안전 영역 크기의 최댓값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 지도의 세로 크기 N과 가로 크기 M이 주어진다. (3 ≤ N, M ≤ 8)

둘째 줄부터 N개의 줄에 지도의 모양이 주어진다. 0은 빈 칸, 1은 벽, 2는 바이러스가 있는 위치이다. 2의 개수는 2보다 크거나 같고, 10보다 작거나 같은 자연수이다.

빈 칸의 개수는 3개 이상이다.

출력

첫째 줄에 얻을 수 있는 안전 영역의 최대 크기를 출력한다.

 

간단한 DP문제 였음 반복 재귀로 좌표 찍고 그 좌표에 대한 배열 결과를 저장했다가 배열로 부터 값을 끌어오고 

크면 업데이트 

실수 -> x범위가 M인데 자꾸 N by N 으로 착각하네....

 

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

using namespace std;


int arr[8][8];




int N,M;
vector<pair<int,int> > vec;


int maxa = 0;

int check()
{
	int temp[8][8];
	int count = 0;
	for(int i = 0; i < N; i++)
	{
		for(int j =0; j <M; j++)
		{
			temp[i][j] = arr[i][j];
		}
	}
	
	
	
	queue<pair<int,int> > que;
	
	for(int i = 0; i <vec.size(); i++)
	{
		que.push({vec[i].first,vec[i].second});
	}
	
	while(!que.empty())
	{
		int y = que.front().first;
		int x = que.front().second;
		
		que.pop();
		
		
		if(y-1 >= 0)
		{
			if(temp[y-1][x] == 0)
			{
				temp[y-1][x] = 2;
				count++;
				que.push({y-1,x});
			}
		}
		
		
		if(y+1 < N)
		{
			if(temp[y+1][x] == 0)
			{
				temp[y+1][x] = 2;
				count ++;
				que.push({y+1,x});
			}
			
		}
		
		if(x-1 >= 0)
		{
			if(temp[y][x-1] == 0)
			{
				temp[y][x-1] = 2;
				count++;
				que.push({y,x-1});
			}
			
			
		}
		
		if(x+1 < M)
		{
			if(temp[y][x+1] == 0)
			{
				temp[y][x+1] = 2;
				count++;
				que.push({y,x+1});
				
			}
		}
		
	}
	
	return count;
	
}




int main(void)
{
	
	
	
	cin >> N >> M;
	int count = 0;
	
	
	for(int i = 0; i < N; i++)
	{
		for(int j = 0; j < M; j++)
		{
			
			
			cin >> arr[i][j];
			
			if(arr[i][j] == 2)
			{
				vec.push_back({i,j});
			}
			else if(arr[i][j] == 1)
			{
				count++;
			}
			
		}
	}
	
	
	for(int i =0; i < N; i ++)
	{	
		for(int j = 0; j < M; j++)
		{
			
			
			
			if(arr[i][j] == 0)
			{
				
				arr[i][j] = 1;
				count++;
				
				
				for(int k = 0; k < N; k++)
				{
					for(int l = 0; l < M; l++)
					{
									
						
						if(arr[k][l] == 0)
						{
							
							arr[k][l] = 1;
							count++;
							
							
							for(int x = 0; x < N; x++)
							{
								for(int y = 0; y < M; y++)
								{
									
									if(arr[x][y] == 0)
									{
										arr[x][y] = 1;
										count++;
										
										int num = N*M-check()-count-vec.size();
									
										 
										
										arr[x][y] = 0;
										count--;
										
										if(num > maxa)
										{
											//cout <<"벽의 위치 "<<i<<","<<j<<" "<<k<<","<<l<<" "<<x<<","<<y<<" "<<"안전 영역 "<<num<<endl;
											maxa = num;
										}
									}
									
								}
							}
							

							
							arr[k][l] = 0;
							count--;							
							
						}		
						

					}

				}
				
				arr[i][j] = 0;
				count--;
				
				
			}
			
			
			
		}
	}
	
	cout << maxa << endl;
	
	
}
반응형