4740. 밍이의 블록게임
시간을 꽤나 써버린 문제이다. 기본적으로 시뮬레이션 문제에, 블록 최대 크기를 구하는 부분에서는 DFS문제를 이용했다.
U,L,R,D 이 네가지 경우로 케이스를 나누어서 문제를 풀었다.
U 같은 경우에는 일단 check() 함수를 통해서 배열의 맨 상단의 한줄이 비어있는지 확인하는데 사용했다. 만약 비어있다면 새로운 줄을 추가
할 수 있다는 것이고, 그렇지 않다면 새로운 줄을 추가할 수 없다. 처음에 이 부분에서 실수한 점은 맨 처음에는 can_add 라는 변수를 쓰지 않고 check() 함수를 두번 호출했는데, 그럴경우 처음 호출에서는 true 가 나왔음에도 두번째 check() 함수에서는 MOVE_UP() 함수를 통해서 밑에 한줄을 추가해서 두번째 check() 함수에서는 false 값이 나올 수 있다는 점이었다. 그래서 이부분을 수정하고, 모든 칸을 아래로 옮기는 방식은 for문 2개와 while 문을 이용해서 구현하였다.
L , R 의 경우는 비슷한 경우였는데, 왼쪽이나 오른쪽으로 밀고 빈 공간이 생겼을 수 있기 때문에 아래로 밀어줘야했다. 처음에 문제를 풀 때 그냥 왼쪽, 오른쪽으로 한번만 밀었는데, 이 경우에는 빈 공간이 또 생길 수 있기 때문에 아래로 밀어줘야 했다.
D 같은 경우에는 처음 DFS를 이용해서 각 덩어리의 최대 크기를 구하였다. 그리고 그 최대값을 변수 M에 저장하였다. 그리고 map_num 에는 각 덩어리들의 크기를 덩어리 중 하나에 넣었다. 그래서 두번째 DFS에서는 map_num 과 최대값인 M인 같은 지역을 DFS를 돌려서 모두 빈 공간으로 만들어주는 작업을 실행했다. 그리고 그 후에는 아래로 밀어서 빈 공간을 없애는 방식으로 문제를 풀었다. 문제를 풀면서 자꾸 놓쳤던 부분은 , 맵의 크기가 N * M 이기 때문에 N,M 을 자꾸 구분하지 않고 M을 N으로 쓰는 실수가 많았다. 그러다보니 디버깅 과정에서 자꾸 눈에 보이지 않았다. 조금만 더 신경을 써서 이런 실수를 줄여야겠다.
<정답 코드>
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 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | #include<iostream> #define MAX 31 using namespace std; int n, m, q; char map[MAX][MAX]; int map_num[MAX][MAX]; bool visited[MAX][MAX]; int dx[4] = { 0,0,1,-1 }; int dy[4] = { 1,-1,0,0 }; void init() { for (int i = 0; i < MAX; i++) { for (int j = 0; j < MAX; j++) { visited[i][j] = false; } } } void MOVE_UP() { for (int i = 1; i < n; i++) { for (int j = 0; j < m; j++) { if (map[i][j] != '#') map[i - 1][j] = map[i][j]; } } } void dfs(int x,int y,char c,int* cnt,int M,bool erase) { (*cnt)++; visited[x][y] = true; for (int d = 0; d < 4; d++) { int nx = x + dx[d]; int ny = y + dy[d]; if (nx >= 0 && ny >= 0 && nx < n && ny < m && !visited[nx][ny] && map[nx][ny] == c) { dfs(nx, ny, c, cnt, M, erase); } } if (erase) map[x][y] = '#'; } bool check() { for (int i = 0; i < n; i++) { if (map[0][i] != '#') return false; } return true; } int main() { //freopen("input.txt", "r", stdin); int tc; cin >> tc; for (int t = 1; t <= tc; t++) { init(); cin >> n >> m >> q; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cin >> map[i][j]; } } for (int i = 0; i < q; i++) { char cs; cin>>cs; if (cs == 'U') { bool can_add = false; if (check()) { MOVE_UP(); // 모든 줄 위로 한칸씩 땡겨서 아랫줄 비우기 can_add = true; } // 맨 아래칸 채우기 for (int j = 0; j < m; j++) { char tmp; cin >> tmp; if (can_add) { // 맨 아랫줄 추가할 수 있는지 확인 map[n - 1][j] = tmp; // 맨 아랫줄 추가 } } // 아래로 밀기 for (int b = 0; b < m; b++) { for (int a = n - 1; a >= 0; a--) { if (map[a][b] != '#') { int x = a, y = b; int c = map[a][b]; while (x + 1 >= 0 && y >= 0 && x + 1 < n && y < m && map[x + 1][y] == '#') { map[x][y] = '#'; map[x + 1][y] = c; x++; } } } } } else if (cs == 'L') { // 왼쪽으로 밀기 for (int a = 0; a < n; a++) { for (int b = 0; b < m; b++) { if (map[a][b] != '#') { int x = a, y = b; int c = map[a][b]; while (x >= 0 && y-1 >= 0 && x < n && y-1 < m && map[x][y-1] == '#') { map[x][y] = '#'; map[x][y-1] = c; y--; } } } } // 아래로 밀기 for (int b = 0; b < m; b++) { for (int a = n - 1; a >= 0; a--) { if (map[a][b] != '#') { int x = a, y = b; int c = map[a][b]; while (x + 1 >= 0 && y >= 0 && x + 1 < n && y < m && map[x + 1][y] == '#') { map[x][y] = '#'; map[x + 1][y] = c; x++; } } } } } else if (cs == 'R') { // 오른쪽 밀기 for (int a = 0; a < n; a++) { for (int b = m-1; b >= 0; b--) { if (map[a][b] != '#') { int x = a, y = b; int c = map[a][b]; while (x >= 0 && y+1 >= 0 && x < n && y+1 < m && map[x][y + 1] == '#') { map[x][y] = '#'; map[x][y + 1] = c; y++; } } } } // 아래로 밀기 for (int b = 0; b < m; b++) { for (int a = n - 1; a >= 0; a--) { if (map[a][b] != '#') { int x = a, y = b; int c = map[a][b]; while (x + 1 >= 0 && y >= 0 && x + 1 < n && y < m && map[x + 1][y] == '#') { map[x][y] = '#'; map[x + 1][y] = c; x++; } } } } } else if (cs == 'D') { int M = 0; // 가장 큰 덩어리 크기 // visited 초기화 for (int i = 0; i < MAX; i++) { for (int j = 0; j < MAX; j++) { visited[i][j] = false; map_num[i][j] = 0; } } // dfs로 가장 큰 덩어리 MAX값 찾기 for (int a = 0; a < n; a++) { for (int b = 0; b < m; b++) { if (map[a][b] != '#' && !visited[a][b]) { int cnt = 0; dfs(a, b, map[a][b],&cnt, M, false); map_num[a][b] = cnt; if (cnt > M) M = cnt; } } } // visited 초기화 for (int i = 0; i < MAX; i++) { for (int j = 0; j < MAX; j++) { visited[i][j] = false; } } // MAX값을 갖는 덩어리 없애기 for (int a = 0; a < n; a++) { for (int b = 0; b < m; b++) { if (map_num[a][b]==M) { int cnt; // 필요없음 dfs(a, b, map[a][b], &cnt, M,true); // 덩어리 큰 값들 삭제하기 } } } // 아래로 밀기 for (int b = 0; b < m; b++) { for (int a = n - 1; a >= 0; a--) { if (map[a][b] != '#') { int x = a, y = b; int c = map[a][b]; while (x + 1 >= 0 && y >= 0 && x + 1 < n && y < m && map[x + 1][y] == '#') { map[x][y] = '#'; map[x + 1][y] = c; x++; } } } } } } cout << "#" << t << endl; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cout << map[i][j]; } cout << endl; } cout << endl; } return 0; } | cs |
'알고리즘 > SW EXPERT' 카테고리의 다른 글
4676. 늘어지는 소리 만들기 (0) | 2018.08.02 |
---|---|
4698. 테네스의 특별한 소수 (0) | 2018.07.30 |
4615. 재미있는 오셀로 게임 (0) | 2018.07.19 |
4751. 다솔이의 다이아몬드 장식 (0) | 2018.07.17 |
3421. 수제 버거 장인 (0) | 2018.04.10 |