BOJ 30055 - 우주비행사 정민 링크
(2024.04.13 기준 P5)
크기의 차원 에 정민이가 위치에 있고, 크기의 차원 에 우주선이 위치에 있다.
블랙홀은 처음에 개가 있다. 이 블랙홀은 우주의 기류에 따라 매초 새로운 블랙홀을 생성한다.
기류는 행 번호가 짝수일 때는 열 번호가 증가하는 방향으로 흐르고, 홀수일 때는 감소하는 방향으로 흐른다. 더 이상 이동할 수 없으면 행 번호가 증가하는 방향으로 한 번 흐른다. 에 도달하면 으로 이동하여 같은 방식으로 순환한다.
차원 이동 게이트는 각 차원에 의 같은 크기로 하나씩 존재한다. 위치는 다를 수 있다. 게이트를 이용해 다른 차원에 초 후 도착할 수 있다. 이때, 동일한 게이트 내부 좌표로 이동한다. 또한 차원 이동하는 초 동안은 블랙홀에 휩쓸리지 않는다.
정민이가 우주선에 도착하는 최단 시간 출력
구현 많은 BFS 문제
문제 지문 그대로 구현하면 된다.
일단 각 칸마다 블랙홀이 도착하는 시간을 구하자.
그리고 정민이의 위치인 (차원, 행, 열)부터 BFS를 진행하면 된다.
이때, 주의해야 할 점은 두 가지가 있다.
1. 항상 어느 칸으로 이동할 땐, 그 칸에 도착하는 시간이 블랙홀이 도착하는 시간보다 일찍이어야 한다.
2. 게이트를 이용할 때, 차원 에서 차원 로도 이용할 수 있다.
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
typedef tuple<int, int, int> tiii;
const int inf = 1e9;
const pii dir[4] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int main(){
ios_base::sync_with_stdio(0);
cin.tie(0);
int K, N1, M1, N2, M2, A, B, R1, C1, R2, C2;
cin >> K >> N1 >> M1 >> N2 >> M2 >> A >> B >> R1 >> C1 >> R2 >> C2;
// 블랙홀이 도달하는 거리 구하기
int dist1_[N1][M1]; fill(&dist1_[0][0], &dist1_[N1 - 1][M1], inf); // 차원 1
int dist2_[N2][M2]; fill(&dist2_[0][0], &dist2_[N2 - 1][M2], inf); // 차원 2
queue<tiii> q;
for (int d, r, c; K; K--){
cin >> d >> r >> c;
if (d == 1){
dist1_[r][c] = 0;
q.push({1, r, c});
}
else{
dist2_[r][c] = 0;
q.push({2, r, c});
}
}
while (!q.empty()){
auto [d, r, c] = q.front(); q.pop();
int nr = r, nc;
if (nr & 1) nc = c - 1;
else nc = c + 1;
if (d == 1){
if (nr & 1){
if (nc == -1) ++nr, ++nc;
}
else{
if (nc == M1) ++nr, --nc;
}
if (nr == N1) nr = nc = 0;
}
else{
if (nr & 1){
if (nc == -1) ++nr, ++nc;
}
else{
if (nc == M2) ++nr, --nc;
}
if (nr == N2) nr = nc = 0;
}
if (d == 1){
if (dist1_[nr][nc] > dist1_[r][c] + 1){
dist1_[nr][nc] = dist1_[r][c] + 1;
q.push({d, nr, nc});
}
}
else{
if (dist2_[nr][nc] > dist2_[r][c] + 1){
dist2_[nr][nc] = dist2_[r][c] + 1;
q.push({d, nr, nc});
}
}
}
if (dist1_[0][0] == 0){
cout << "hing...";
return 0;
}
// 정민이의 시작 위치부터 BFS 시작
int dist1[N1][M1]; fill(&dist1[0][0], &dist1[N1 - 1][M1], inf); // 차원 1
int dist2[N2][M2]; fill(&dist2[0][0], &dist2[N2 - 1][M2], inf); // 차원 2
dist1[0][0] = 0;
q.push({1, 0, 0});
// 항상 블랙홀이 도달하는 시간보다 더 일찍 도착해야 한다.
while (!q.empty()){
auto [d, r, c] = q.front(); q.pop();
if (d == 1 && R1 <= r && r < R1 + A && C1 <= c && c < C1 + B){ // 차원 1에서 게이트를 이용할 수 있다.
int nr = R2 + r - R1, nc = C2 + c - C1;
if (dist2[nr][nc] > dist1[r][c] + 3 && dist2_[nr][nc] > dist1[r][c] + 3){
dist2[nr][nc] = dist1[r][c] + 3;
q.push({2, nr, nc});
}
}
if (d == 2 && R2 <= r && r < R2 + A && C2 <= c && c < C2 + B){ // 차원 2에서 게이트를 이용할 수 있다.
int nr = R1 + r - R2, nc = C1 + c - C2;
if (dist1[nr][nc] > dist2[r][c] + 3 && dist1_[nr][nc] > dist2[r][c] + 3){
dist1[nr][nc] = dist2[r][c] + 3;
q.push({1, nr, nc});
}
}
// 상하좌우 이동
if (d == 1){
for (auto [dr, dc]: dir){
if (0 <= r + dr && r + dr < N1 && 0 <= c + dc && c + dc < M1 && dist1[r + dr][c + dc] > dist1[r][c] + 1 && dist1_[r + dr][c + dc] > dist1[r][c] + 1){
dist1[r + dr][c + dc] = dist1[r][c] + 1;
q.push({d, r + dr, c + dc});
}
}
}
else{
for (auto [dr, dc]: dir){
if (0 <= r + dr && r + dr < N2 && 0 <= c + dc && c + dc < M2 && dist2[r + dr][c + dc] > dist2[r][c] + 1 && dist2_[r + dr][c + dc] > dist2[r][c] + 1){
dist2[r + dr][c + dc] = dist2[r][c] + 1;
q.push({d, r + dr, c + dc});
}
}
}
}
if (dist2[N2 - 1][M2 - 1] < inf) cout << dist2[N2 - 1][M2 - 1];
else cout << "hing...";
}
import sys; input = sys.stdin.readline
from math import inf
from collections import deque
dir = [(-1, 0), (1, 0), (0, -1), (0, 1)]
K, N1, M1, N2, M2 = map(int, input().split())
A, B = map(int, input().split())
R1, C1 = map(int, input().split())
R2, C2 = map(int, input().split())
# 블랙홀이 도달하는 거리 구하기
dist1_ = [[inf] * M1 for _ in range(N1)] # 차원 1
dist2_ = [[inf] * M2 for _ in range(N2)] # 차원 2
dq = deque()
for _ in range(K):
d, r, c = map(int, input().split())
if d == 1:
dist1_[r][c] = 0
dq.append((1, r, c))
else:
dist2_[r][c] = 0
dq.append((2, r, c))
while dq:
d, r, c = dq.popleft()
nr = r
if nr & 1:
nc = c - 1
else:
nc = c + 1
if d == 1:
if nr & 1:
if nc == -1:
nr += 1; nc += 1
else:
if nc == M1:
nr += 1; nc -= 1
if nr == N1:
nr = nc = 0
else:
if nr & 1:
if nc == -1:
nr += 1; nc += 1
else:
if nc == M2:
nr += 1; nc -= 1
if nr == N2:
nr = nc = 0
if d == 1:
if dist1_[nr][nc] > dist1_[r][c] + 1:
dist1_[nr][nc] = dist1_[r][c] + 1
dq.append((d, nr, nc))
else:
if dist2_[nr][nc] > dist2_[r][c] + 1:
dist2_[nr][nc] = dist2_[r][c] + 1
dq.append((d, nr, nc))
if dist1_[0][0] == 0:
print('hing...')
exit()
# 정민이의 시작 위치부터 BFS 시작
dist1 = [[inf] * M1 for _ in range(N1)] # 차원 1
dist2 = [[inf] * M2 for _ in range(N2)] # 차원 2
dist1[0][0] = 0
dq.append((1, 0, 0))
# 항상 블랙홀이 도달하는 시간보다 더 일찍 도착해야 한다.
while dq:
d, r, c = dq.popleft()
if d == 1 and R1 <= r < R1 + A and C1 <= c < C1 + B: # 차원 1에서 게이트를 이용할 수 있다.
nr = R2 + r - R1; nc = C2 + c - C1
if dist2[nr][nc] > dist1[r][c] + 3 and dist2_[nr][nc] > dist1[r][c] + 3:
dist2[nr][nc] = dist1[r][c] + 3
dq.append((2, nr, nc))
if d == 2 and R2 <= r < R2 + A and C2 <= c < C2 + B: # 차원 2에서 게이트를 이용할 수 있다.
nr = R1 + r - R2; nc = C1 + c - C2
if dist1[nr][nc] > dist2[r][c] + 3 and dist1_[nr][nc] > dist2[r][c] + 3:
dist1[nr][nc] = dist2[r][c] + 3
dq.append((1, nr, nc))
# 상하좌우 이동
if d == 1:
for dr, dc in dir:
if 0 <= r + dr < N1 and 0 <= c + dc < M1 and dist1[r + dr][c + dc] > dist1[r][c] + 1 and dist1_[r + dr][c + dc] > dist1[r][c] + 1:
dist1[r + dr][c + dc] = dist1[r][c] + 1
dq.append((d, r + dr, c + dc))
else:
for dr, dc in dir:
if 0 <= r + dr < N2 and 0 <= c + dc < M2 and dist2[r + dr][c + dc] > dist2[r][c] + 1 and dist2_[r + dr][c + dc] > dist2[r][c] + 1:
dist2[r + dr][c + dc] = dist2[r][c] + 1
dq.append((d, r + dr, c + dc))
if dist2[N2 - 1][M2 - 1] < inf:
print(dist2[N2 - 1][M2 - 1])
else:
print('hing...')