깔끔한 코드는 도저히 생각이 나지 않아서 경우의 수들에 대해 하드코딩 했다......
가장 중요한 아이디어는 rx, ry, bx, by를 매개변수로 받아 지점에 대한 타당성을 검증하는 것인거 같다.
1. 직전에 상하로 움직였으면 이번엔 좌우만 움직여보고, 직전에 좌우로 움직였으면 상하로만 움직인다.
2. 파란공을 먼저 움직여보고 타당하면 빨간공을 움직인다.
3. 빨간공까지 움직였을때 빨간공과 파란공의 위치가 같은경우 인자로 받아왔던 rx,ry,bx,by 값을 비교해 둘중 하나를 한칸 옮겨준다.
4. cnt가 10이하인 모든 방법을 탐색한다.
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 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | #include <iostream> #include <algorithm> #include <string> #define INF 20 using namespace std; int n, m, rx, ry, bx, by, res; int map[10][10]; void dfs(int rx,int ry,int bx,int by,int dir,int cnt) { if (cnt == 11) return; bool next_flag = false; int rrx = rx; int rry = ry; int bbx = bx; int bby = by; //직전칸에서 좌우로 움직인 경우 if (dir == 1) { //위 방향 for (int i = bbx - 1; i >=0; i--) { if (map[i][bby] == 'O') { break; } if (map[i][bby] == '#') { bbx = i + 1; next_flag = true; break; } } if (next_flag) { for (int i = rrx - 1; i >= 0; i--) { if (map[i][rry] == 'O') { res = min(res, cnt); break; } if (map[i][rry] == '#') { rrx = i + 1; if (rrx == bbx && ry==by) { if (rx > bx) rrx += 1; else bbx += 1; } dfs(rrx, rry, bbx, bby, 2, cnt + 1); break; } } } //아래 방향 next_flag = false; rrx = rx; rry = ry; bbx = bx; bby = by; for (int i = bbx + 1; i < n; i++) { if (map[i][bby] == 'O') { break; } if (map[i][bby] == '#') { bbx = i - 1; next_flag = true; break; } } if (next_flag) { for (int i = rrx + 1; i < n; i++) { if (map[i][rry] == 'O') { res = min(res, cnt); break; } if (map[i][rry] == '#') { rrx = i - 1; if (rrx == bbx && ry == by) { if (rx > bx) bbx -= 1; else rrx -= 1; } dfs(rrx, rry, bbx, bby, 2, cnt + 1); break; } } } } //직전칸에서 상하로 움직인 경우 else if (dir == 2) { next_flag = false; rrx = rx; rry = ry; bbx = bx; bby = by; //왼쪽 방향 for (int i = bby - 1; i >= 0; i--) { if (map[bbx][i] == 'O') { break; } if (map[bbx][i] == '#') { bby = i + 1; next_flag = true; break; } } if (next_flag) { for (int i = rry - 1; i >= 0; i--) { if (map[rrx][i] == 'O') { res = min(res, cnt); break; } if (map[rrx][i] == '#') { rry = i + 1; if (rx == bx && rry == bby) { if (ry > by) rry += 1; else bby += 1; } dfs(rrx, rry, bbx, bby, 1, cnt + 1); break; } } } next_flag = false; rrx = rx; rry = ry; bbx = bx; bby = by; //오른쪽 방향 for (int i = bby + 1; i < m; i++) { if (map[bbx][i] == 'O') { break; } if (map[bbx][i] == '#') { bby = i - 1; next_flag = true; break; } } if (next_flag) { for (int i = rry + 1; i < m; i++) { if (map[rrx][i] == 'O') { res = min(res, cnt); break; } if (map[rrx][i] == '#') { rry = i - 1; if (rx == bx && rry == bby) { if (ry > by) bby -= 1; else rry -= 1; } dfs(rrx, rry, bbx, bby, 1, cnt + 1); break; } } } } } int main() { ios_base::sync_with_stdio(false); cin >> n >> m; for (int i = 0; i < n; i++) { string buf; cin >> buf; for (int j = 0; j < m; j++) { map[i][j] = buf[j]; if (map[i][j] == 'R') { rx = i; ry = j; } if (map[i][j] == 'B') { bx = i; by = j; } } } res = INF; dfs(rx, ry, bx, by, 1, 1); dfs(rx, ry, bx, by, 2, 1); if (res == INF) cout << -1 << endl; else cout << res << endl; return 0; } | cs |
'BOJ::문제풀이' 카테고리의 다른 글
12851 숨바꼭질 2 (0) | 2018.03.26 |
---|---|
1600 말이 되고픈 원숭이 (0) | 2018.03.26 |
14500 테트로미노 (0) | 2018.03.25 |
4179 불! (0) | 2018.03.25 |
5558 치 ~ 즈 (0) | 2018.03.24 |