BAEKJOON/그래프
백준 1600번 [말이 되고픈 원숭이](C++) -yes6686- 티스토리
yes6686
2025. 6. 21. 20:29
728x90
반응형
SMALL
백준 문제 풀이: 1600 (말이 되고픈 원숭이)
문제 링크: https://www.acmicpc.net/problem/1600
문제 설명:
원숭이가 일반적인 상하좌우 4방향 이동 외에도, 최대 K번까지는 말처럼 L자 점프(8방향)를 할 수 있을 때, (0,0)에서 (w-1,h-1)로 이동하는 데 필요한 최소 이동 횟수를 구하는 문제입니다. 맵에는 장애물(1)이 있을 수 있고, 점프는 장애물을 넘을 수 없습니다. 이동 불가능한 경우 -1을 출력합니다.
문제 해결 코드
// 1600번: 말이 되고픈 원숭이
// 일반 이동 + 말 점프(BFS) with 3차원 visited 배열
#include <iostream>
#include <queue>
using namespace std;
int arr[201][201]; // 격자 정보
int visited[201][201][31]; // [x][y][k번 말점프 사용 여부]
int dx[4] = { 1, -1, 0, 0 };
int dy[4] = { 0, 0, 1, -1 };
int hx[8] = { -2, -1, 1, 2, -2, -1, 1, 2 };
int hy[8] = { -1, -2, -2, -1, 1, 2, 2, 1 };
int minAns = 40001;
int w, h;
queue<pair<pair<int, int>, pair<int, int>>> q; // ((x, y), (총 이동횟수, 말점프 횟수))
void bfs(int x, int y, int k) {
q.push({ {x, y}, {0, 0} });
visited[x][y][0] = 1;
while (!q.empty()) {
auto [pos, state] = q.front(); q.pop();
int kx = pos.first, ky = pos.second;
int cnt = state.first, u = state.second;
// 일반 4방향 이동
for (int i = 0; i < 4; i++) {
int nx = kx + dx[i];
int ny = ky + dy[i];
if (nx < 0 || ny < 0 || nx >= w || ny >= h) continue;
if (arr[nx][ny] == 1 || visited[nx][ny][u]) continue;
visited[nx][ny][u] = 1;
if (nx == w - 1 && ny == h - 1) {
minAns = min(minAns, cnt + 1);
continue;
}
q.push({ {nx, ny}, {cnt + 1, u} });
}
// 말처럼 점프 (최대 k번까지 가능)
if (u < k) {
for (int i = 0; i < 8; i++) {
int nx = kx + hx[i];
int ny = ky + hy[i];
if (nx < 0 || ny < 0 || nx >= w || ny >= h) continue;
if (arr[nx][ny] == 1 || visited[nx][ny][u + 1]) continue;
visited[nx][ny][u + 1] = 1;
if (nx == w - 1 && ny == h - 1) {
minAns = min(minAns, cnt + 1);
continue;
}
q.push({ {nx, ny}, {cnt + 1, u + 1} });
}
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
int k;
cin >> k;
cin >> h >> w;
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
cin >> arr[i][j];
}
}
bfs(0, 0, k);
if (h == 1 && w == 1) {
cout << 0 << '\n';
} else if (minAns == 40001) {
cout << -1 << '\n';
} else {
cout << minAns << '\n';
}
}
코드 설명
- 핵심 알고리즘: BFS + 3차원 visited 배열
- 상태 표현: (x, y) 위치 + 말 점프 횟수
- 중요 조건: 같은 칸이라도 점프 횟수가 다르면 다른 상태로 처리
- 도착 즉시
minAns
갱신
결과
(0,0)에서 (w-1,h-1)까지 최소 이동 횟수를 출력합니다. 도달 불가 시 -1
출력.
예시 입력:
1
4 4
0 0 0 0
1 0 0 0
0 0 1 0
0 1 0 0
예시 출력:
4
다른 접근 방식이나 개선 아이디어가 있다면 댓글로 공유해주세요!
728x90
반응형
LIST