※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 3860번 문제인 할로윈 묘지이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/3860
3860번: 할로윈 묘지
오늘은 할로윈이다. 상근이와 친구들은 할로윈을 기념하기 위해 묘지를 방문했다. 상근이와 친구들은 한 명씩 묘지로 들어가고, 혼자서 묘지의 출구를 찾아야 한다. 이제, 상근이의 차례가 돌아
www.acmicpc.net
귀신구멍을 이용하면 시간이 과거로 돌아가므로 음의 간선을 처리할 수 있는 최단거리 알고리즘을 이용하자.
글쓴이는 Bellman-Ford 알고리즘을 이용하였다.
주어진 묘지에서는 다음과 같은 움직임을 할 수 없다:
- 어떤 칸에서 묘비로 이동하는 움직임
- 묘비, 또는 귀신 구멍칸에서 주변 칸으로 이동하는 움직임
- 묘지 출구에서 주변 칸으로 이동하는 움직임
출력의 우선순위에도 신경을 쓰자:
- 상근이가 끝없이 과거로 돌아갈 수 있다면 Never 출력
- 그렇지 않고, 상근이가 묘지를 탈출할 수 없다면 Impossible 출력
- 그렇지 않다면 묘지 탈출까지의 최단시간을 출력
위의 출력우선순위는 원문을 참고하였다.
이런 내용을 주의하여 구현한다면 이 문제를 해결할 수 있을 것이다.
아래는 제출한 소스코드이다.
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
typedef long long ll;
struct edge {
int x, y;
ll d;
edge(int x, int y, ll d) {
this->x = x, this->y = y, this->d = d;
}
};
vector<edge> edges;
int field[30][30]; // 2: 묘비
ll dist[900];
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int R, C; cin >> C >> R;
while (R) {
edges.clear();
memset(field, 0, sizeof(field));
int G; cin >> G;
while (G--) {
int r, c; cin >> c >> r;
field[r][c] = 2;
}
int E; cin >> E;
while (E--) {
int r1, c1, r2, c2, d; cin >> c1 >> r1 >> c2 >> r2 >> d;
edges.emplace_back(edge(r1 * C + c1, r2 * C + c2, d));
field[r1][c1] = 1;
}
field[R - 1][C - 1] = 3;
for (int r = 0; r < R; r++) {
for (int c = 0; c < C; c++) {
if (field[r][c]) continue;
if (r > 0) {
if (!(field[r - 1][c] == 2)) edges.emplace_back(edge(r * C + c, (r - 1) * C + c, 1));
}
if (r < R - 1) {
if (!(field[r + 1][c] == 2)) edges.emplace_back(edge(r * C + c, (r + 1) * C + c, 1));
}
if (c > 0) {
if (!(field[r][c - 1] == 2)) edges.emplace_back(edge(r * C + c, r * C + c - 1, 1));
}
if (c < C - 1) {
if (!(field[r][c + 1] == 2)) edges.emplace_back(edge(r * C + c, r * C + c + 1, 1));
}
}
}
int RC = R * C;
dist[0] = 0;
for (int i = 1; i < RC; i++) dist[i] = 1000000000;
for (int i = 1; i < RC; i++) {
for (auto e : edges) {
if (dist[e.x] < 1000000000) dist[e.y] = min(dist[e.y], dist[e.x] + e.d);
}
}
bool chk = 1;
for (auto e : edges) {
if (dist[e.x] < 1000000000) {
if (dist[e.y] > dist[e.x] + e.d) chk = 0;
}
}
if (chk) {
if (dist[RC - 1] == 1000000000) cout << "Impossible\n";
else cout << dist[RC - 1] << '\n';
}
else cout << "Never\n";
cin >> C >> R;
}
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 6002 // C++] Job Hunt (0) | 2021.12.16 |
---|---|
[BOJ 13317 // C++] 한 번 남았다 (0) | 2021.12.15 |
[BOJ 1738 // C++] 골목길 (0) | 2021.12.13 |
[BOJ 7577 // C++] 탐사 (0) | 2021.12.12 |
[BOJ 7634 // C++] Guessing Game (0) | 2021.12.11 |