BOJ : https://www.acmicpc.net/problem/14502
14502번: 연구소
인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다. 연구소는 크기가 N×M인 직사각형으로 나타낼 수 있으며, 직사각형은 1×1 크기의 정사각형으로 나누어져 있다. 연구소는 빈 칸, 벽으로 이루어져 있으며, 벽은 칸 하나를 가득 차지한다. 일부 칸은 바이러스가 존재하며, 이 바이러스는 상하좌우로 인접한 빈 칸으로 모두 퍼져나갈 수 있다.
www.acmicpc.net
이 문제를 해결하는데 필요한 알고리즘 : BFS or Brute force (or DFS)
나는 BFS로 풀었다.
처음에는 배열의 크기를 생각하지 못하고 시간초과 없이 어떻게 해결해야하나 했는데
8*8 크기라면 전범위를 다돌아도 괜찮을 것 같았다.
바이러스가 없는 0 부분에 1을 2칸 집어넣고 1칸씩 옮겨가면서 경우의 수를 다 구해줬다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int arr[8][8];
int ans[8][8];
int Arr[8][8];
int temp[4] = { -1,1,0,0 };
int temp2[4] = { 0,0,-1,1 };
typedef pair<int, int> pii;
vector<pii> v;
int MAX, first, second;
int N, M, virus;
bool visit;
bool check[8][8];
void dfs(int n, int m) { // n -> 세로 m -> 가로
for (int i = 0; i < 4; i++) {
if (n + temp[i] >= 0 && n + temp[i] < N && m + temp2[i] >= 0 && m + temp2[i] < M) {
if (arr[n + temp[i]][m + temp2[i]] == 0) {
arr[n + temp[i]][m + temp2[i]] = 2;
dfs(n + temp[i], m + temp2[i]);
}
}
}
}
void lab() {
if (virus == 3) {
int zero = 0;
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
ans[i][j] = arr[i][j];
for (int i = 0; i < v.size(); i++) {
dfs(v[i].first, v[i].second);
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (arr[i][j] == 0) zero++;
arr[i][j] = ans[i][j];
ans[i][j] = Arr[i][j];
}
}
MAX = max(MAX, zero);
return;
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (i == N-1 && j == M-1)
visit = true;
if (arr[i][j] == 0) {
if (!check[i][j]) {
if (virus == 1)
check[i][j] = true, first = i, second = j;
arr[i][j] = 1, virus++;
lab();
if (i != first || j != second)
arr[i][j] = 0, virus--;
}
}
if (visit == true) {
if (i == first && j == second) {
visit = false;
if (first != N - 1 || second != M - 1) {
arr[first][second] = 0, virus--;
if (second != M - 1) {
j = second;
}
else {
i = first;
j = -1;
}
}
}
else return;
}
}
}
}
int main() {
cin >> N >> M;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
cin >> arr[i][j];
Arr[i][j] = arr[i][j];
if (arr[i][j] == 2) v.push_back(make_pair(i, j));
}
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (arr[i][j] == 0) {
arr[i][j] = 1, virus = 1, visit = false;
lab();
if (Arr[N - 1][M - 1] != 1)
if (arr[N - 1][M - 1] == 1) arr[N - 1][M - 1] = 0;
arr[i][j] = 0;
}
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
check[i][j] = false;
}
}
cout << MAX;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
|
'algorithm > BOJ' 카테고리의 다른 글
6603번 : 로또 - junnnho (0) | 2019.04.07 |
---|---|
1182번 : 부분수열의 합 - junnnho (0) | 2019.04.07 |
16235번 : 나무제테크 - Junnnho (0) | 2019.04.07 |
BOJ 1463번 1로 만들기 (0) | 2019.04.07 |
BOJ 1965번 상자넣기 (0) | 2019.04.07 |