코딩문제 풀이

백준 14502번 연구소

student513 2020. 1. 14. 14:09
 

14502번: 연구소

인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다. 연구소는 크기가 N×M인 직사각형으로 나타낼 수 있으며, 직사각형은 1×1 크기의 정사각형으로 나누어져 있다. 연구소는 빈 칸, 벽으로 이루어져 있으며, 벽은 칸 하나를 가득 차지한다.  일부 칸은 바이러스가 존재하며, 이 바이러스는 상하좌우로 인접한 빈 칸으로 모두 퍼져나갈 수 있다.

www.acmicpc.net

 

구조는 간단하지만 상당히 까다로웠던 문제.

 

문제는 크게 두 부분으로 나뉜다.

 

1. 연구소의 벽 세우기

2. 바이러스 퍼뜨리기

 

처음에 문제를 접했을 때 완전탐색(브루트포스)를 숙지하지 않았기 때문에 벽을 어떻게 세워야할지에서부터

 

막혔었다. 3중 for문을 생각했지만 택도 없었다.

 

백준 N과 M 문제집을 전부 풀고 나서 완전탐색에 관한 감을 잡았다.

 

벽을 세운 이후에는 BFS를 이용하여 인접 좌표들에 바이러스를 퍼뜨린 결과를 counting하면 끝.

 

#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;

int N, M, cnt;
vector<int> arr[9];
vector<int> temp_vec[9];
int temp[9][9];
bool visited[9][9];
queue<pair<int,int>> que;
int dir[4][2] = { {-1,0},{0,1},{1,0},{0,-1} };
vector<pair<int, int>> vir_vec;
vector<int> result;
bool vist_arr[9][9];

void print() {
	
	cout << '\n';
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			cout << arr[i][j] << " ";
		}
		cout << '\n';
	}
	/*
	cout << '\n';
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			cout << temp_vec[i][j]<<" ";
		}
		cout << '\n';
	}
	*/
}

void bfs() {
	for (int i = 0; i < 9; i++) {
		memset(visited[i], false, sizeof(visited[i]));
	}
	for(int i = 0; i < vir_vec.size(); i++) {
		que.push(make_pair(vir_vec[i].first, vir_vec[i].second));
		visited[vir_vec[i].first][vir_vec[i].second] = true;

		while (!que.empty()) {
			int x = que.front().first; int y = que.front().second;
			que.pop();
			for (int j = 0; j < 4; j++) {
				int dir_x = x + dir[j][0]; int dir_y = y + dir[j][1];
				if (0 <= dir_x && dir_x < N && 0 <= dir_y && dir_y < M) {
					if (arr[dir_x][dir_y] == 0 && !visited[dir_x][dir_y]) {
						visited[dir_x][dir_y] = true;
						que.push(make_pair(dir_x, dir_y));
						arr[dir_x][dir_y] = 2;
					}
				}
			}
		}
	}
}

void func(int cnt) {
	if (cnt == 3) {
		int temp = 0;
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < M; j++) {
				temp_vec[i][j] = arr[i][j];
			}
		}

		bfs();//바이러스 퍼뜨리기

		for (int i = 0; i < N; i++){//안전구역 count하기
			for (int j = 0; j < M; j++) {
				if (arr[i][j] == 0) {
					temp++;
				}
			}
		}
		result.push_back(temp);

		for (int i = 0; i < N; i++) {
			for (int j = 0; j < M; j++) {
				arr[i][j] = temp_vec[i][j];
			}
		}
		return;
	}

	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			if (arr[i][j] == 0 ){
				arr[i][j] = 1;
				func(cnt + 1);
				arr[i][j] = 0;//한번 끝내고 나면 arr를 다시 원래대로 돌려줘야 한다. 
			}
		}
	}
}
int main() {
	cin >> N >> M;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			int temp;
			cin >> temp; arr[i].push_back(temp);
			if (temp == 2) {
				vir_vec.push_back(make_pair(i,j));
			}
		}
	}
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			temp_vec[i].push_back(arr[i][j]);
		}
	}

	func(0);
	
	sort(result.begin(), result.end());

	cout << result.back();

	return 0;
}

 

참고자료

 

문제집: N과 M (baekjoon)

 

www.acmicpc.net

 

'코딩문제 풀이' 카테고리의 다른 글

14891번 톱니바퀴  (0) 2020.01.21
14888번 연산자 끼워넣기  (0) 2020.01.17
14889번 스타트와 링크  (0) 2020.01.16
14503번 로봇 청소기  (0) 2020.01.15
백준 14890번 경사로  (0) 2020.01.08