BOJ::문제풀이
14502 연구소
2영재
2018. 1. 27. 15:38
BOJ::14502 연구소
https://www.acmicpc.net/problem/14502
1. 2차원 배열에서 백트래킹을 통해 벽을 세우는 모든 경우에 대해 탐색.
2. 벽을 3개 세웠으면 바이러스를 퍼뜨림.
3. 안전영역 갯수를 카운팅.
4. 최대값 출력.
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 | #include <iostream> #include <memory.h> #include <algorithm> using namespace std; int n, m, res; int map[8][8]; bool visited[8][8]; int dx[] = { 1,-1,0,0 }; int dy[] = { 0,0,1,-1 }; void spread_virus(int x,int y) { visited[x][y] = true; for (int i = 0; i < 4; i++) { int ax = x + dx[i]; int ay = y + dy[i]; if (ax >= 0 && ay >= 0 && ax < n&&ay < m && !visited[ax][ay] && map[ax][ay] == 0) { spread_virus(ax, ay); } } } void get_result() { int ans = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (map[i][j] == 0 && !visited[i][j]) ans++; } } res = max(res, ans); } void dfs(int x,int y,int cnt) { map[x][y] = 1; //벽 3개 세움 if (cnt == 3) { for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (map[i][j] == 2) spread_virus(i, j); } } get_result(); memset(visited, 0, sizeof(visited)); } else { //같은라인 for (int i = y+1; i < m; i++) { if(map[x][i]==0) dfs(x, i, cnt + 1); } //다음라인부터 for (int i = x + 1; i < n; i++) { for (int j = 0; j < m; j++) { if(map[i][j] == 0) dfs(i, j, cnt + 1); } } } map[x][y] = 0; } int main() { ios_base::sync_with_stdio(false); cin.tie(0); cin >> n >> m; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cin >> map[i][j]; } } for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (map[i][j] == 0) dfs(i, j, 1); } } cout << res << endl; } | cs |
------- 예전에 풀었던 방법 ---------
처음 벽을 세우는 경우에 대해 신박한 방법 없나? 라는 생각을 가지고 열심히 생각해봤지만....
벽을 3개 세울 수 있는 모든경우에 대해 찾아보는거 말고는 방법이 떠오르지 않았다.
그래서 벽을 3개 세울 수 있는 모든 경우에 대해 벽을 세워보고 안전지역 개수를 카운팅하여 풀었다.
보통 map 배열을 2차원으로 놓는데, 2차원으로는 어떤식으로 3개를 놓아야 할지 모르겠어서
map 을 1차원으로 두고 백트래킹 하여 풀었다.
n x m 배열에서 2차원처럼 인덱싱 할때는 map[ i / m ][ i % m ] 을 이용하면 된다.
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 | #include <stdio.h> #include <memory.h> int n, m, res; int map[8*8]; int visited[8][8]; int dx[] = { 1,-1,0,0 }; int dy[] = { 0,0,1,-1 }; int getSafetyZone() { int cnt = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (map[i*m + j] == 0 && !visited[i][j]) { cnt++; } } } return cnt; } void spreadVirus(int x,int y) { for (int i = 0; i < 4; i++) { int ax = x + dx[i]; int ay = y + dy[i]; if (ax >= 0 && ay >= 0 && ax < n&&ay < m) { if (!visited[ax][ay] && map[m*ax+ay] == 0) { visited[ax][ay] = true; spreadVirus(ax, ay); } } } } void solve(int v, int cnt) { //벽 세우기 map[v] = 1; //벽을 3개 세웠으면 카운팅 if (cnt == 3) { memset(visited, 0, sizeof(visited)); //바이러스 퍼뜨리기 for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (map[m*i + j] == 2) { spreadVirus(i,j); } } } //안전지역 갯수 세기 int cnt=getSafetyZone(); if (res < cnt) { res = cnt; } } else { for (int i = v + 1; i < n*m; i++) { if (map[i] == 0) { solve(i, cnt + 1); } } } map[v] = 0; } int main() { scanf("%d %d", &n, &m); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { scanf("%d", &map[i*m + j]); } } for (int i = 0; i < n*m; i++) { if (map[i] == 0) { solve(i, 1); } } printf("%d\n", res); } | cs |