티스토리 뷰
문제
동물원에서 막 탈출한 원숭이 한 마리가 세상구경을 하고 있다. 그 녀석은 말(Horse)이 되기를 간절히 원했다. 그래서 그는 말의 움직임을 유심히 살펴보고 그대로 따라 하기로 하였다. 말은 말이다. 말은 격자판에서 체스의 나이트와 같은 이동방식을 가진다. 다음 그림에 말의 이동방법이 나타나있다. x표시한 곳으로 말이 갈 수 있다는 뜻이다. 참고로 말은 장애물을 뛰어넘을 수 있다.
x | x | |||
x | x | |||
말 | ||||
x | x | |||
x | x |
근데 원숭이는 한 가지 착각하고 있는 것이 있다. 말은 저렇게 움직일 수 있지만 원숭이는 능력이 부족해서 총 K번만 위와 같이 움직일 수 있고, 그 외에는 그냥 인접한 칸으로만 움직일 수 있다. 대각선 방향은 인접한 칸에 포함되지 않는다.
이제 원숭이는 머나먼 여행길을 떠난다. 격자판의 맨 왼쪽 위에서 시작해서 맨 오른쪽 아래까지 가야한다. 인접한 네 방향으로 한 번 움직이는 것, 말의 움직임으로 한 번 움직이는 것, 모두 한 번의 동작으로 친다. 격자판이 주어졌을 때, 원숭이가 최소한의 동작으로 시작지점에서 도착지점까지 갈 수 있는 방법을 알아내는 프로그램을 작성하시오.
입력
첫째 줄에 정수 K가 주어진다. 둘째 줄에 격자판의 가로길이 W, 세로길이 H가 주어진다. 그 다음 H줄에 걸쳐 W개의 숫자가 주어지는데, 0은 아무것도 없는 평지, 1은 장애물을 뜻한다. 장애물이 있는 곳으로는 이동할 수 없다. 시작점과 도착점은 항상 평지이다. W와 H는 1이상 200이하의 자연수이고, K는 0이상 30이하의 정수이다.
출력
첫째 줄에 원숭이의 동작수의 최솟값을 출력한다. 시작점에서 도착점까지 갈 수 없는 경우엔 -1을 출력한다.
문제 풀이
- 좌상단에서 우하단까지의 최단거리를 구하는 문제여서 BFS 방식으로 문제를 풀었습니다.
- visited 함수의 경우 말처럼 이동할 수 있는 횟수가 제한이 되어 있어서 말처럼 이동이 가능한 경우 만큼 visited 함수를 통해 표시 할 수 있게 하였습니다.
- 기존의 BFS 처럼 queue를 이용해서 다음 칸으로 이동이 가능할 경우 queue에 다음칸 정보를 append하였습니다.
- 이 때 원숭이 처럼 이동하는 경우와 말처럼 이동하는 경우를 나누어 진행 하였습니다.
- 여기서 고민했던 것이 말처럼 말처럼 이동하는 경우가 발생하기 때문에 visited 최소값 갱신을 어떻게 해줘야 하지 고민을 하다가 visited에 말로움직일 수 있는 경우의 수를 넣어서 최솟값 갱신이 아닌 말처럼 움직인 횟수를 추가로 저장해서 현재칸 까지 오는 경우를 갱신하였습니다.
- 도착하지 못할 경우엔 -1을 출력 하게 하였습니다.
import sys
from collections import deque
input = sys.stdin.readline
k = int(input())
m,n= map(int,input().split())
a = []
for _ in range(n):
a.append(list(map(int, input().split())))
visited = [[[0] * (k+1) for _ in range(m)] for _ in range(n)]
q = deque([(0,0,k)])
move = [(0,1),(1,0),(0,-1),(-1,0)]
h_move = [(1,2),(2,1),(2,-1),(1,-2),(-1,-2),(-2,-1),(-2,1),(-1,2)]
answer = float('inf')
while q:
i,j,h = q.popleft()
if i == n-1 and j == m-1:
answer = min(answer, visited[i][j][h])
continue
for k in move:
ii = i + k[0]
jj = j + k[1]
if 0 <= ii < n and 0 <= jj < m and a[ii][jj] == 0:
if visited[ii][jj][h] == 0:
visited[ii][jj][h] = visited[i][j][h] + 1
q.append((ii,jj,h))
for k in h_move:
if h == 0:
break
ii = i + k[0]
jj = j + k[1]
if 0 <= ii < n and 0 <= jj < m and a[ii][jj] == 0:
if visited[ii][jj][h-1] == 0:
visited[ii][jj][h-1] = visited[i][j][h] + 1
q.append((ii,jj,h-1))
print(answer if answer != float('inf') else -1)
'코딩테스트' 카테고리의 다른 글
[프로그래머스] 미로탈출 명령어 (0) | 2023.11.10 |
---|---|
[프로그래머스] 표현 가능한 이진트리 (0) | 2023.11.01 |
[백준 22862] 가장 긴 짝수 연속한 부분 수열(Large) (0) | 2023.08.04 |
- Total
- Today
- Yesterday
- CSS
- 가장 긴 짝수 연속한 부분 수열
- node 버전 마이그레이션
- useCallback과 useMemo 사용
- serverless nestjs
- javascript
- 서버사이드 error handling
- storybook react is not defiend 해결
- nextjs errorboundary
- 선언적 UI
- serverless 배포
- 서비스 디자인 패턴
- 백준 1600번
- 자바스크립트
- React useCallback
- suspense 장점
- storybook scss이슈
- 백준 22862
- nestjs 배포하기
- React useMemo
- 관심사 분리하기
- react suspense
- nextjs 에러핸들링
- 1600 파이썬
- 표현 가능한 이진트리
- 에러핸들링
- storybook scss import
- 불량 사용자 자바스크립트
- 미로탈출 명령어
- node version yarn berry
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |