16173번: 점프왕 쩰리 (Small)
문제 )
‘쩰리’는 점프하는 것을 좋아하는 젤리다. 단순히 점프하는 것에 지루함을 느낀 ‘쩰리’는 새로운 점프 게임을 해보고 싶어 한다. 새로운 점프 게임의 조건은 다음과 같다.
- ‘쩰리’는 가로와 세로의 칸 수가 같은 정사각형의 구역 내부에서만 움직일 수 있다. ‘쩰리’가 정사각형 구역의 외부로 나가는 경우엔 바닥으로 떨어져 즉시 게임에서 패배하게 된다.
- ‘쩰리’의 출발점은 항상 정사각형의 가장 왼쪽, 가장 위의 칸이다. 다른 출발점에서는 출발하지 않는다.
- ‘쩰리’가 이동 가능한 방향은 오른쪽과 아래 뿐이다. 위쪽과 왼쪽으로는 이동할 수 없다.
- ‘쩰리’가 가장 오른쪽, 가장 아래 칸에 도달하는 순간, 그 즉시 ‘쩰리’의 승리로 게임은 종료된다.
- ‘쩰리’가 한 번에 이동할 수 있는 칸의 수는, 현재 밟고 있는 칸에 쓰여 있는 수 만큼이다. 칸에 쓰여 있는 수 초과나 그 미만으로 이동할 수 없다.
새로운 게임이 맘에 든 ‘쩰리’는, 계속 게임을 진행해 마침내 최종 단계에 도달했다. 하지만, 게임을 진행하는 구역이 너무 넓어져버린 나머지, 이 게임에서 이길 수 있는지 없는지 가늠할 수 없어졌다. ‘쩰리’는 유능한 프로그래머인 당신에게 주어진 구역에서 승리할 수 있는 지 알아봐 달라고 부탁했다. ‘쩰리’를 도와 주어진 게임 구역에서 끝 점(오른쪽 맨 아래 칸)까지 도달할 수 있는지를 알아보자!
입력 :
입력의 첫 번째 줄에는 게임 구역의 크기 N (2 ≤ N ≤ 3)이 주어진다.
입력의 두 번째 줄부터 마지막 줄까지 게임판의 구역(맵)이 주어진다.
게임판의 승리 지점(오른쪽 맨 아래 칸)에는 -1이 쓰여있고, 나머지 칸에는 0 이상 100 이하의 정수가 쓰여있다.
출력 :
‘쩰리’가 끝 점에 도달할 수 있으면 “HaruHaru”(인용부호 없이), 도달할 수 없으면 “Hing” (인용부호 없이)을 한 줄에 출력합니다.
풀이)
일단 이 문제를 보았을때 쩰리가 게임판의 승리 지점까지 갈 수 있는 모든 경우의 수를 파악해
승리지점의 도착 유무를 파악해야 하므로, 백트래킹 방법을 먼저 생각했다.
따라서 재귀함수를 먼저 생각했고 그 코드는 다음과 같다.
1. 백트래킹 풀이
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
|
import sys
sys.setrecursionlimit(10**6)
def recur(a, b, cnt):
global answer
if -1 < a < n and -1 < b < n:
if a == n - 1 and b == n - 1:
answer = min(answer, cnt)
return
move = g[a][b]
if move > 0:
recur(a + move, b, cnt + 1)
recur(a, b + move, cnt + 1)
n = int(input())
g = [list(map(int, input().split())) for i in range(n)]
answer = 9999
recur(0, 0, 0)
if answer == 9999:
print("Hing")
else:
print("HaruHaru")
|
cs |
밟은 곳의 숫자에 따라 점프하므로, 이 숫자가 0이게 되면 무한루프에 빠져 메모리 초과가 뜨게 되므로
move는 양수로 제한한다.
이후 재귀를 이용하여 쩰리가 좌측으로 점프하는 경우와 아랫 방향으로 점프하는 모든 경우에 대해 추적하도록 했다.
맨 처음의 조건에 따라 게임 구역을 벗어나게 된 재귀들은 자연스레 없어지게 되고 승리 지점에 도착하면 최소 점프 횟수를
answer 라는 함수에 담게 했다.
이 문제를 풀 당시에는 DFS, BFS를 사용할 생각을 하지 못했지만..
다른 분의 코드를 보고 다시 한번 문제를 풀어보았다.
2. DFS
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
|
def DFS():
di = [1, 0]
dj = [0, 1]
while stack:
a, b = stack.pop()
if a == n - 1 and b == n - 1:
return True
if g[a][b] != 0:
for i in range(2):
x = a + di[i] * g[a][b]
y = b + dj[i] * g[a][b]
if -1 < x < n and -1 < y < n:
stack.append([x, y])
return False
n = int(input())
g = [list(map(int, input().split())) for i in range(n)]
# 무조건 0,0 에서 출발하므로 입력값은 넣지 않았다.
stack = [[0, 0]]
if DFS():
print("HaruHaru")
else:
print("Hing")
|
cs |
큰 대략적인 조건들은 재귀방식과 동일하다.
이 문제에서 체크해야 할 것은
쩰리가 점프할 수 있는 칸 수가0이 아니도록 조건을 달아야 하고,이 칸수를 이용하여 한번에 건너는 거리를 조절하는 것 같다.
출처 : https://www.acmicpc.net/problem/16173
16173번: 점프왕 쩰리 (Small)
쩰리는 맨 왼쪽 위의 칸에서 출발해 (행, 열)로 나타낸 좌표계로, (1, 1) -> (2, 1) -> (3, 1) -> (3, 3)으로 이동해 게임에서 승리할 수 있다.
www.acmicpc.net
'Develop > 백준 (python)' 카테고리의 다른 글
[백준] 14562번: 태권왕 (python) (0) | 2022.03.06 |
---|---|
[백준] 1388번: 바닥 장식 (python) (0) | 2022.03.06 |
[백준] 7569번: 토마토 (python) (0) | 2022.03.05 |
[백준] 7576번: 토마토 (python) (0) | 2022.03.04 |
[백준] 2583번: 영역 구하기 (python) (0) | 2022.03.03 |