BOJ 34966 방바닥 정리하기
sorohue가 PS하는 블로그
BOJ 34966 방바닥 정리하기
문제 링크입니다.
문제 요약
격자 위에 두 종류의 물건과 구멍이 있습니다. 각 구멍을 이동시켜 같은 종류의 물건을 제거할 수 있습니다. 다른 종류의 물건을 넘어갈 수는 없습니다. 구멍을 한 번 이동시킬 때 원하는 만큼 움직이면서 물건들을 지울 수 있습니다.
구멍을 움직여야 하는 최소 횟수를 구하세요.
풀이
구멍을 한 번 집었으면 지울 수 있는 물건은 싹 다 지워버리는 게 무조건 이득입니다. 또 같은 구멍을 두 번 연속해서 이동시킬 이유가 없습니다.
두 구멍을 어떻게 이동시켜도 서로 닿을 수 없는 경우는 모든 물건을 치우는 게 불가능하고, 그렇지 않다면 두 번의 이동 이내로 두 구멍이 만날 수밖에 없습니다.
두 구멍이 만난 이후에는 구멍이 합쳐진 셈 치고 상태를 바꿔야 하는 최소 개수로 접근을 해 볼 수 있습니다. 그러면 문제가 최단 경로 문제와 동등함을 알 수 있고, 다익스트라든 다이얼이든 구현하면 맞을 수 있습니다.
저는 A부터 움직이는 경우와 B부터 움직이는 경우로 나눠서 다이얼을 두 번 돌리는 풀이로 해결했습니다.
코드
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
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
const int dx[] = {-1,1,0,0}, dy[] = {0,0,-1,1};
const int INF = 9998244353;
char a[1234][1234];
int Ax, Ay, Bx, By, n, m, d[1234][1234]; bool isa, isb;
int solve(int ay, int ax, int by, int bx, bool c){
queue<int> q[3]; q[0].push(ay); q[0].push(ax);
for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) d[i][j] = INF; d[ay][ax] = 0;
int now = 0;
while(q[0].size() || q[1].size() || q[2].size()){
while(q[0].empty()) swap(q[0], q[1]), swap(q[1], q[2]), now++;
while(q[0].size()){
int y = q[0].front(); q[0].pop();
int x = q[0].front(); q[0].pop();
if(d[y][x] < now) continue;
for(int dir = 0; dir < 4; dir++){
int ny = y+dy[dir], nx = x+dx[dir];
if(ny <= 0 || nx <= 0 || ny > n || nx > n) continue;
int nd = d[y][x]+(a[ny][nx] == ('a'+(c^(now&1)))); if(a[ny][nx] == ('a'+!c) && !now) nd = 2;
if(d[ny][nx] <= nd) continue; d[ny][nx] = nd; q[nd-now].push(ny); q[nd-now].push(nx);
}
}
}
if(d[by][bx] > 1) return INF;
return now;
}
int main(){
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
cin >> n >> m; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++){
cin >> a[i][j]; if(a[i][j] == 'A') Ay = i, Ax = j; if(a[i][j] == 'B') By = i, Bx = j;
if(a[i][j] == 'a') isa = 1; if(a[i][j] == 'b') isb = 1;
}
if(!isa && !isb) return !(cout << 0);
if(!isa || !isb) return !(cout << 1);
int ans = INF; ans = min(ans, solve(Ay, Ax, By, Bx, 0)); ans = min(ans, solve(By, Bx, Ay, Ax, 1));
if(ans == INF) ans = -1; cout << ans;
}
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.