BOJ 4485. 녹색 옷 입은 애가 젤다지?
1. 문제설명
- 동굴의 크기
N
N*N
크기의 맵에는 0~9까지의 가중치가 존재한다.- (1,1)에서 시작해 (N,N)까지의 최단 경로를 구하라
2. 알고리즘 설계
- 가중치가 음수가 없으면서 여러개라면?
- 다익스트라
3. 로직
priority_queue
를 사용해 BFS 방식으로 탐색하면 된다.- 가중치가 적은 순서대로 pq의 앞에 쌓는다.
- 탐색 도중 N, N을 만나면 현재까지의 weight를 출력한다.
- 구현의 편의상 (0,0) ~ (N-1,N-1)까지로 설정하였다.
4. 전체 코드
#include <bits/stdc++.h>
using namespace std;
const int SZ = 125;
const int dy[] = { -1,1,0,0 };
const int dx[] = { 0,0,-1,1 };
int n;
int arr[SZ][SZ];
bool visited[SZ][SZ];
int bfs(void)
{
priority_queue<tuple<int,int,int>> pq;
pq.push({ -arr[0][0], 0, 0 });
visited[0][0] = true;
while (!pq.empty()) {
auto cur = pq.top();
pq.pop();
int cy = get<1>(cur);
int cx = get<2>(cur);
int w = get<0>(cur);
if (cy == n - 1 && cx == n - 1)
return w;
for (int dir = 0; dir < 4; dir++) {
int ny = cy + dy[dir];
int nx = cx + dx[dir];
if (ny < 0 || nx < 0 || ny >= n || nx >= n)
continue;
if (!visited[ny][nx]) {
pq.push({ w - arr[ny][nx], ny, nx });
visited[ny][nx] = true;
}
}
}
}
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int i = 1;
while (true) {
cin >> n;
if (n == 0) break;
fill_n(&arr[0][0], SZ * SZ, 0);
fill_n(&visited[0][0], SZ * SZ, false);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cin >> arr[i][j];
cout << "Problem " << i++ << ": " << - bfs() << '\n';
}
return 0;
}
5. 소감
tuple
- 세가지 자료형을 담는 자료구조
-
접근 방법
tuple<int,int,int> Tuple; get<0>(Tuple); // 나머지 두개는 1, 2로 접근 auto [a, b, c] = Tuple // 한번에 값 가져오는 방법
- 굳이
tuple
을 사용한 이유- 예전에 언급했었는데, 구조체를 사용하면 operator까지 직접 구현해야 한다.
pair
,tuple
등을 사용하면 가장 앞에 있는 인자값 기준으로 정렬되어 삽입된다.pair
는first
,tuple
은 0번째 값 기준
- 전체 코드에서 볼 수 있듯이 음수값으로 값을 저장한다.
- pq는 default가
max_heap
으로, 큰 값을 기준으로 정렬된다. - ’~’를 씌운 값을 넣으면
min_heap
의 효과가 있다.
- pq는 default가
- 해당 문제는 weight가 0~9사이의 값이다.
- 이렇게 weight 개수가 적은 경우 다이얼 알고리즘을 사용하면,
- 속도 측면에서 이득을 챙길 수 있다고 한다.