이번 문제는 얼듯 보면 미로를 백트래킹(또는 깊이우선탐색) 등으로 풀어나갈 것 같지만, 벽을 가는 곳을 간선 웨이트를 1로, 벽이 없는 곳을 간선 웨이트 0으로 생각하고 다익스트라 알고리즘을 적용하면 풀기 편합니다.
https://www.acmicpc.net/problem/2665
제가 작성한 소스의 설명입니다. 일반적인 다익스트라 알고리즘을 이용했는데, 우선순위큐에 저장될 값들을 비트연산을 통해서 정수형(int)로 만들어서 했습니다.
1. **입력 받기**: 사용자로부터 미로의 크기 \( n \)과 미로의 지도를 입력받습니다.
2. **우선순위 큐 사용**: 미로의 각 방을 탐색하기 위해 우선순위 큐를 사용합니다. 이 큐는 현재 경로에서 흰 방으로 바꿔야 할 검은 방의 수를 우선순위로 사용합니다.
3. **탐색 초기화**: 탐색을 시작하기 위해 시작 위치(0, 0)를 큐에 넣고, 이미 방문한 방을 표시하기 위해 해당 위치를 'v'로 마크합니다.
4. **탐색 수행**: 큐가 비어있지 않을 때까지 다음 과정을 반복합니다:
- 큐에서 현재 위치와 지금까지 바꾼 검은 방의 수를 꺼냅니다.
- 현재 위치가 목표 위치(n-1, n-1)인지 확인하고, 도달했다면 지금까지 바꾼 검은 방의 수를 출력하고 종료합니다.
- 현재 위치에서 이동할 수 있는 4방향(상하좌우)을 검사하여 유효한 위치로 이동합니다. 만약 이동할 위치가 검은 방이라면, 큐에 추가할 때 흰 방으로 바꿔야 하므로 카운트를 증가시킵니다. 이동할 위치를 'v'로 마크하여 중복 방문을 방지합니다.
5. **종료**: 목표 위치에 도달했을 때 결과를 출력하고 프로그램을 종료합니다.
제가 작성한 소스입니다.
//------------------------------------------------
// baekjoon #2665
// - by Aubrey Choi
// - created at 2019-07-12
//------------------------------------------------
#include <stdio.h>
#include <queue>
int main()
{
int n;
char map[50][51];
std::priority_queue<int> queue;
scanf("%d", &n);
for(int i = 0; i < n; i++) scanf("%s", map[i]);
queue.push(1000<<16);
map[0][0] = 'v';
while(!queue.empty())
{
int t = queue.top();
queue.pop();
int p = 1000-(t >> 16), r = (t >> 8) & 255, c = t & 255;
if(r == n - 1 && c == n - 1)
{
printf("%d\n", p);
break;
}
const int d[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
for(int i = 0; i < 4; i++)
{
int nr = r + d[i][0], nc = c + d[i][1];
if(nr < 0 || nr >= n || nc < 0 || nc >= n || map[nr][nc] == 'v') continue;
if(map[nr][nc] == '0') queue.push(((999 - p) << 16) | (nr << 8) | nc);
else queue.push(((1000 - p) << 16) | (nr << 8) | (nc));
map[nr][nc] = 'v';
}
}
return 0;
}
'Programming > BOJ' 카테고리의 다른 글
[C/C++] 백준 #2668 숫자고르기(순환구조 탐색) (0) | 2024.06.04 |
---|---|
[C/C++] 백준 #2667 단지번호붙이기(깊이우선탐색) (0) | 2024.06.03 |
[C/C++] 백준 #2661 좋은수열(백트래킹) (0) | 2024.05.30 |
[C/C++] 백준 #2660 회장뽑기(플로이드-워샬) (0) | 2024.05.21 |
[C/C++] 백준 #2636 치즈(깊이우선탐색) (0) | 2024.05.14 |
댓글