n*n 크기의 맵에서 장애물이 m개가 있을 때 최대로 놓을 수 있는 비숍의 수를 구하는 문제이다.
/대각선과 \대각선을 맵에 grouping 해주고, / -> \ 로 가는(역방향도 상관없다) 간선을 만들어 준 후 이분매칭을 하면 된다.
이분매칭을 하는 이유는 i(/) 대각선과 j(\) 대각선을 매칭 했을 때 가장 많은 쌍의 개수를 구하기 위함이다.
<코드>
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 | #include <stdio.h> #include <vector> #include <algorithm> using namespace std; int n, m, map[101][101], map2[101][101]; vector<vector<int>> v(10001); vector<bool> c(10001); vector<int> p(10001, -1); // 이분매칭 int dfs(int x) { if (x == -1) return 1; for (auto i : v[x]) { if (c[i]) continue; c[i] = true; if (dfs(p[i])) { p[i] = x; return 1; } } return 0; } int main() { scanf("%d%d", &n, &m); while (m--) { int a, b; scanf("%d%d", &a, &b); map[a][b] = -1; } int cnt = 1, i, j, k; // 대각선 grouping for (k = 0; k < n; k++) { i = 1; j = n - k; bool c = false; for (; j <= n; i++, j++) { if (!map[i][j]) { map[i][j] = cnt; c = true; } if (map[i][j] == -1 && c) cnt++, c = false; } if (c) cnt++; } for (k = 1; k < n; k++) { i = 1 + k; j = 1; bool c = false; for (; i <= n; i++, j++) { if (!map[i][j]) { map[i][j] = cnt; c = true; } if (map[i][j] == -1 && c) cnt++, c = false; } if (c) cnt++; } for (k = 0; k < n; k++) { i = 1; j = 1 + k; bool c = false; for (; j > 0; i++, j--) { if (map[i][j] != -1) { map2[i][j] = cnt; c = true; } if (map[i][j] == -1 && c) cnt++, c = false; } if (c) cnt++; } for (k = 1; k < n; k++) { i = 1 + k, j = n; bool c = false; for (; j > 0; i++, j--) { if (map[i][j] != -1) { map2[i][j] = cnt; c = true; } if (map[i][j] == -1 && c) cnt++, c = false; } if (c) cnt++; } cnt = m = 0; for (i = 1; i <= n; i++) for (j = 1; j <= n; j++) { if (map[i][j] != -1) v[map[i][j]].push_back(map2[i][j]); m = max(m, map[i][j]); } for (i = 1; i <= m; i++) { fill(c.begin(), c.end(), false); cnt += dfs(i); } printf("%d\n", cnt); return 0; } | cs |
'BOJ' 카테고리의 다른 글
11664 선분과 점 (0) | 2017.08.30 |
---|---|
1069 집으로 (0) | 2017.08.30 |
2316 도시 왕복하기 (0) | 2017.08.30 |
14671 영정이의 청소 (0) | 2017.08.30 |
9333 돈 갚기 (0) | 2017.08.30 |