https://www.acmicpc.net/problem/1261
문제
알고스팟 운영진이 모두 미로에 갇혔다. 미로는 N*M 크기이며, 총 1*1크기의 방으로 이루어져 있다. 미로는 빈 방 또는 벽으로 이루어져 있고, 빈 방은 자유롭게 다닐 수 있지만, 벽은 부수지 않으면 이동할 수 없다.
알고스팟 운영진은 여러명이지만, 항상 모두 같은 방에 있어야 한다. 즉, 여러 명이 다른 방에 있을 수는 없다. 어떤 방에서 이동할 수 있는 방은 상하좌우로 인접한 빈 방이다. 즉, 현재 운영진이 (x, y)에 있을 때, 이동할 수 있는 방은 (x+1, y), (x, y+1), (x-1, y), (x, y-1) 이다. 단, 미로의 밖으로 이동 할 수는 없다.
벽은 평소에는 이동할 수 없지만, 알고스팟의 무기 AOJ를 이용해 벽을 부수어 버릴 수 있다. 벽을 부수면, 빈 방과 동일한 방으로 변한다.
만약 이 문제가 알고스팟에 있다면, 운영진들은 궁극의 무기 sudo를 이용해 벽을 한 번에 다 없애버릴 수 있지만, 안타깝게도 이 문제는 Baekjoon Online Judge에 수록되어 있기 때문에, sudo를 사용할 수 없다.
현재 (1, 1)에 있는 알고스팟 운영진이 (N, M)으로 이동하려면 벽을 최소 몇 개 부수어야 하는지 구하는 프로그램을 작성하시오.
입력
첫째 줄에 미로의 크기를 나타내는 가로 크기 M, 세로 크기 N (1 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 미로의 상태를 나타내는 숫자 0과 1이 주어진다. 0은 빈 방을 의미하고, 1은 벽을 의미한다.
(1, 1)과 (N, M)은 항상 뚫려있다.
출력
첫째 줄에 알고스팟 운영진이 (N, M)으로 이동하기 위해 벽을 최소 몇 개 부수어야 하는지 출력한다.
문제 풀이
다익스트라 알고리즘을 이용하는 문제.
벽을 부수는 개수가 낮은 순서대로 꺼내는 우선 순위 큐를 이용해 다익스트라 알고리즘을 구현해주면 된다. 먼저 특정 위치까지 가는데 부수어야 하는 벽의 개수를 저장하는 N * M 배열을 만든다. 큐에는 위치와 해당 위치까지 가는데 부수어야 하는 벽의 개수를 pair<벽의 개수, pair<x, y>>의 형태로 저장한다. 그리고 우선 순위 큐가 빌 때까지 현재 top을 꺼내와 해당 위치와 그 위치까지 가는 데 벽을 부수는 개수를 얻어온다. 인접한 네 개의 방을 확인하며 해당 위치까지 도달하는데 부수는 벽의 개수를 줄일 수 있다면 배열을 업데이트해준다. 만약 큐의 top으로부터 얻어진 부수어야 하는 벽의 개수가 배열의 값보다 크다면 탐색해야 할 이유가 없으므로 continue를 작성해주면 된다.
아래는 코드.
#include <iostream>
#include <queue>
#include <utility>
#define MAX 987654321
using namespace std;
int N, M;
int** arr;
int** distances;
int dx[] = { -1, 0, 0, 1 };
int dy[] = { 0, -1, 1, 0 };
void dijkstra()
{
priority_queue<pair<int, pair<int, int>>, vector<pair<int, pair<int, int>>>, greater<pair<int, pair<int, int>>>> pq;
pq.push(pair(0, pair(0, 0)));
while (!pq.empty())
{
pair<int, pair<int, int>> current = pq.top();
int x = current.second.first;
int y = current.second.second;
int cost = current.first;
pq.pop();
if (cost > distances[x][y])
{
continue;
}
for (int i = 0; i < 4; i++)
{
int nextX = x + dx[i];
int nextY = y + dy[i];
if (nextX >= 0 && nextX < N && nextY >= 0 && nextY < M)
{
int currentCost = cost + arr[nextX][nextY];
if (distances[nextX][nextY] > currentCost)
{
distances[nextX][nextY] = currentCost;
pq.push(pair(currentCost, pair(nextX, nextY)));
}
}
}
}
}
int main()
{
cin.tie(NULL);
ios::sync_with_stdio(false);
string str;
cin >> M >> N;
arr = new int*[N];
distances = new int*[N];
for (int i = 0; i < N; i++)
{
cin >> str;
arr[i] = new int[M];
distances[i] = new int[M];
for (int j = 0; j < M; j++)
{
arr[i][j] = str.at(j) - 48;
distances[i][j] = MAX;
}
}
distances[0][0] = 0;
dijkstra();
cout << distances[N - 1][M - 1] << "\n";
return 0;
}
'알고리즘 > 백준' 카테고리의 다른 글
[백준 5639] 이진 검색 트리 (C++) (0) | 2024.10.11 |
---|---|
[백준 11564] 점프왕 최준민 (C++) (0) | 2024.10.10 |
[백준 10431] 줄세우기 (C++) (0) | 2024.10.08 |
[백준 31589] 포도주 시음 (C++) (0) | 2024.10.07 |
[백준 22858] 원상 복구 (small) (C++) (0) | 2024.10.06 |