문제
https://www.acmicpc.net/problem/1600
입력
- 첫째 줄에 정수 K가 주어진다. 둘째 줄에 격자판의 가로길이 W, 세로길이 H가 주어진다. 그 다음 H줄에 걸쳐 W개의 숫자가 주어지는데, 0은 아무것도 없는 평지, 1은 장애물을 뜻한다. 장애물이 있는 곳으로는 이동할 수 없다. 시작점과 도착점은 항상 평지이다. W와 H는 1이상 200이하의 자연수이고, K는 0이상 30이하의 정수이다.
출력
- 첫째 줄에 원숭이의 동작수의 최솟값을 출력한다. 시작점에서 도착점까지 갈 수 없는 경우엔 -1을 출력한다.
입력 예제
1
4 4
0 0 0 0
1 0 0 0
0 0 1 0
0 1 0 0
2
5 2
0 0 1 1 0
0 0 1 1 0
출력 예제
4
-1
문제 풀이
- 말의 움직임은 k번까지만 가능하므로 말과 원숭이의 움직임을 따로 체크
- 3차원 배열을 사용하여 말의 움직임으로 이동했다면 visited[y][x][k + 1]의 형식으로 체크할 수 있음
- 말의 움직임으로 이동했을 때 cnt 증가
- 모든 움직임을 마친 후 목적지에 도달했다면 이동 횟수 리턴
- 목적지에 도달하지 못했다면 -1리턴
코드
from collections import deque
# 말의 움직임
horse = [[-1,-2],[-2,-1],[-2,1],[-1,2],[1,-2],[2,-1],[2,1],[1,2]]
# 상하좌우
dy = [-1,1,0,0]
dx = [0,0,-1,1]
k = int(input())
w, h = map(int,input().split())
graph = []
visited = [[[0] * (k + 1) for _ in range(w)] for _ in range(h)]
for _ in range(h):
graph.append(list(map(int,input().split())))
def bfs(y,x, cnt):
queue = deque()
queue.append((y,x,cnt))
visited[y][x][cnt] = 1
while queue:
y, x, cnt = queue.popleft()
# 종료조건
if y == h - 1 and x == w - 1:
return visited[y][x][cnt] - 1
# 원숭이 이동
for i in range(4):
ny = y + dy[i]
nx = x + dx[i]
if 0 <= ny < h and 0 <= nx < w:
if graph[ny][nx] == 0 and not visited[ny][nx][cnt]:
visited[ny][nx][cnt] = visited[y][x][cnt] + 1
queue.append((ny, nx, cnt))
# 말 이동
if cnt < k:
for (hy, hx) in horse:
ny = y + hy
nx = x + hx
if 0 <= ny < h and 0 <= nx < w:
if graph[ny][nx] == 0 and not visited[ny][nx][cnt + 1]:
visited[ny][nx][cnt + 1] = visited[y][x][cnt] + 1
queue.append((ny, nx, cnt + 1))
return -1
print(bfs(0,0,0))
전형적인 BFS 문제
벽 부수기 문제와 유사하다
유사 문제
'Algorithm > BFS&DFS' 카테고리의 다른 글
| [Python] 백준 11567번 선진이의 겨울왕국 (5) | 2024.08.28 |
|---|---|
| [Python] 백준 2146번 다리 만들기 (3) | 2024.08.27 |
| [Python] 프로그래머스 미로 탈출 (1) | 2024.07.24 |
| [Java] 백준 13165번 침투 (2) | 2023.11.02 |
| [Python] 백준 1240번 노드사이의 거리 (1) | 2023.11.01 |