반응형
문제 출처 :
https://www.acmicpc.net/problem/16234
알고리즘 분석 :
문제 해결에 필요한 사항
1. bfs
2. 구현
이 문제는 문제에 주어진 조건대로만 잘 진행하면 충분히 해결 할 수 있다.
단, 조심해야 할 점은 인구이동을 하는데 하룻동안 인구이동이 여러번 일어나도 하루에는 인구이동 1번으로 취급한다.
bfs에서 벡터에 현재 국가와 연합을 할 수 있는 위치를 모두 담아주고 그 좌표들이 가진 모든 값을 더하여 크기만큼 나누면 인구이동이 완료될 때 인구가 나타난다.
조건을 따라 코딩하는 것은 아래 주석을 통해 달아두었다.
소스 코드 :
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 114 115 116 117 118 119 120 121 122 123 124 125 | #include <iostream> #include <cstdio> #include <algorithm> #include <vector> #include <memory.h> #include <queue> using namespace std; typedef pair<int, int> pii; int abs(int a, int b) { return a > b ? a - b : b - a; } int arr[52][52]; int tmp[52][52]; int alliance[52][52]; bool visit[52][52]; int color; int dy[4] = { -1,0,1,0 }; int dx[4] = { 0,-1,0,1 }; int n, l, r, ans; vector<pii> bfs(int i, int j) { memset(visit, 0, sizeof(visit)); queue<pii> q; vector<pii> vc; q.push({ i,j }); while (!q.empty()) { int y = q.front().first; int x = q.front().second; q.pop(); if (visit[y][x]) continue; alliance[y][x] = color; vc.push_back({ y,x }); visit[y][x] = true; for (int i = 0; i < 4; i++) { int ny = dy[i] + y; int nx = dx[i] + x; // 국경선을 공유하는 두 나라의 인구 차이가 L명 이상, R명 이하라면, // 두 나라가 공유하는 국경선을 오늘 하루동안 연다. // 즉, 큐에 push하여 같은 색을 칠하도록 한다. if (0 <= ny && ny < n && 0 <= nx && nx < n && alliance[ny][nx] == -1) { int val = abs(arr[ny][nx] - arr[y][x]); if (l <= val && val <= r) q.push({ ny,nx }); } } } return vc; } int main() { scanf("%d %d %d", &n, &l, &r); for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) scanf("%d", &arr[i][j]); bool chk = true; while (chk) { for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) tmp[i][j] = arr[i][j]; // 연합을 해체하고, 모든 국경선을 닫는다. chk = false; memset(alliance, -1, sizeof(alliance)); color = 1; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (alliance[i][j] != -1) continue; color++; vector<pii> vc = bfs(i, j); if (vc.size() == 1) continue; // 위의 조건에 의해 열어야하는 국경선이 모두 열렸다면, // 인구 이동을 시작한다. // 국경선이 열려있어 인접한 칸만을 이용해 이동할 수 있으면, // 그 나라를 오늘 하루 동안은 연합이라고 한다. chk = true; int ret = 0; for (int k = 0; k < vc.size(); k++) ret += tmp[vc[k].first][vc[k].second]; // 연합을 이루고 있는 각 칸의 인구수는 // (연합의 인구수) / (연합을 이루고 있는 칸의 개수)가 된다. // 편의상 소수점은 버린다. ret /= vc.size(); for (int k = 0; k < vc.size(); k++) tmp[vc[k].first][vc[k].second] = ret; } } if (!chk) break; ans++; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) arr[i][j] = tmp[i][j]; } return !printf("%d",ans); } // This source code Copyright belongs to Crocus // If you want to see more? click here >> | Crocus |
반응형
'Applied > 알고리즘 문제풀이' 카테고리의 다른 글
[16953번] A → B (0) | 2019.03.05 |
---|---|
[16956번] 늑대와 양 (0) | 2019.03.03 |
[16235번] 나무 재테크 (0) | 2018.10.22 |
[16236번] 아기 상어 (4) | 2018.10.21 |
[14890번] 경사로 (0) | 2018.09.27 |