반응형
리뷰
https://www.acmicpc.net/problem/1600
방향 배열을 두개 사용하고, 방문 배열을 3차원으로 사용하여 푼 문제
전역 변수
- k : 말의 움직임을 할 수 있는 횟수를 저장할 변수
- w : 맵의 가로 길이를 저장할 변수
- h : 맵의 세로 길이를 저장할 변수
- lst : 맵 정보를 저장하기 위한 2차원 배열
- v : 말의 이동을 한 횟수를 기준으로 방문 처리를 하기 위한 3차원 배열
- hx, hy : 말의 이동을 진행할 방향 배열
- dx, dy : 4방향 이동을 진행할 방향 배열
- Pos : 맵 상에서의 이동을 기록할 구조체, 이동 횟수 t를 기준으로 오름차순 정렬한다.
함수
1. dijkstra
int dijkstra()
너비 우선 탐색을 통해 시작점에서 목표지점까지 걸리는 최소 거리를 리턴하기 위한 함수
- Pos타입의 우선순위 큐 pq를 초기화 해주고, 초기값 0, 0, 0, 0을 입력해 준다.
- 초기 지점에 대해 방문처리 후 pq가 빌 때 까지 while루프를 돌아준다.
- 매 루프마다 pq에서 요소 한개씩을 뽑아 구조체의 요소를 각각 cx, cy, ct, cs로 파싱해준다.
- 기저 조건으로 만약 cx, cy가 맵의 오른쪽 하단에 도달했다면 ct를 리턴해 준다.
- 4방향 탐색을 진행하고 맵의 범위 안이면서 방문처리 되지 않았고 벽이 아니라면 이동을 진행한다.
- 이동한 위치에 방문표시 후 pq에 시간을 1 늘린 상태로 이동한 좌표를 push해준다.
- 만약 cs가 k보다 작다면 즉, 말의 이동을 할 수 있는 상태라면
- 8방향 탐색을 진행하고 맵의 범위 안이면서 방문처리 되지 않았고 벽이 아니라면 이동을 진행한다.
- 이동한 위치에 방문표시 후 pq에 시간을 1, 말 이동 횟수를 1늘린 상태로 이동한 좌표를 push해준다.
- 만약 while루프가 종료될 때까지 최소값을 찾지 못했다면 -1을 리턴해 준다.
문제풀이
- k, w, h값을 입력 받고 h * w크기의 맵 정보를 입력 받아 lst배열에 저장해 준다.
- dijkstra함수를 호출한 뒤 리턴 값을 출력해 준다.
트러블 슈팅
- 예제도 모두 맞았고 로직 상 특이 사항이 확인되지 않았으나 제출 하자마자 틀렸습니다를 받았다.
- 문제를 다시 잘 읽어보니 K값의 범위가 0이상 30이하의 정수임을 확인했다.
- 따라서 v배열의 범위를 30에서 31로 늘려주었더니 바로 AC를 받았다.
참고 사항
실제로 다익스트라를 사용하진 않았으니 함수명은 bfs가 맞는 것 같다.
문제를 설계할때 말의 이동을 한 횟수를 기준으로 방문 처리를 해야 특이 사항이 없을 것이라 판단했다.
예를 들어 이동 횟수 기준으로 오름차순만 한 경우 아래같은 경우에는 체크할 수 없다는 생각이 들었다.
1
4 4
0 0 1 1
1 0 1 1
1 0 1 1
1 1 1 0
위의 경우 바로 말의 움직임을 써버려서 (2, 1)로 이동했다면 이미 방문 처리가 되어 있기 때문에 걸어서 갈 수 없다.
따라서 현재까지 사용한 말의 움직임을 기준으로 방문 배열을 사용해 주었다.
정답 코드
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
int k, w, h;
int lst[200][200];
int v[31][200][200];
int hx[] = { -1, -2, -2, -1, 1, 2, 2, 1 };
int hy[] = { -2, -1, 1, 2, 2, 1, -1, -2 };
int dx[] = { 0, 0, 1, -1 };
int dy[] = { 1, -1, 0, 0 };
struct Pos {
int x, y, t, s;
bool operator<(const Pos& other) const {
return t > other.t;
}
};
int dijkstra() {
priority_queue<Pos> pq;
pq.push({ 0, 0, 0, 0 });
v[0][0][0] = 1;
while (!pq.empty()) {
Pos pos = pq.top(); pq.pop();
int cx = pos.x, cy = pos.y, ct = pos.t, cs = pos.s;
if (cx == h - 1 && cy == w - 1) return ct;
for (int i = 0; i < 4; ++i) {
int nx = cx + dx[i], ny = cy + dy[i];
if (0 <= nx && nx < h && 0 <= ny && ny < w && !v[cs][nx][ny] && !lst[nx][ny]) {
v[cs][nx][ny] = 1;
pq.push({ nx, ny, ct + 1, cs });
}
}
if (cs < k) {
for (int i = 0; i < 8; ++i) {
int nx = cx + hx[i], ny = cy + hy[i], ns = cs + 1;
if (0 <= nx && nx < h && 0 <= ny && ny < w && !v[ns][nx][ny] && !lst[nx][ny]) {
v[ns][nx][ny] = 1;
pq.push({ nx, ny, ct + 1, ns });
}
}
}
}
return -1;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> k >> w >> h;
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j)
cin >> lst[i][j];
cout << dijkstra();
}
728x90
반응형
'알고리즘 공부 > C++' 카테고리의 다른 글
[G3] 백준 14442번 벽 부수고 이동하기 2 C++ 너비 우선 탐색, 우선순위 큐 (0) | 2024.12.20 |
---|---|
[G3] 백준 2638번 치즈 C++ 너비 우선 탐색, 해시맵, 구현, 시뮬레이션 (0) | 2024.12.19 |
[G3] 백준 2146번 다리 만들기 C++ 너비 우선 탐색, 플러드 필, 우선순위 큐 (0) | 2024.12.16 |
[G4] 백준 1963번 소수 경로 C++ 너비 우선 탐색, 에라토스테네스의 체 (2) | 2024.12.14 |
[G4] 백준 11559번 Puyo Puyo C++ 너비 우선 탐색, 시뮬레이션, 구현 (3) | 2024.12.13 |