관련 링크 : https://www.acmicpc.net/problem/1103
백준 1103 : 게임
형택이는 1부터 9까지의 숫자와, 구멍이 있는 직사각형 보드에서 재밌는 게임을 한다. 일단 보드의 가장 왼쪽 위에 동전을 하나 올려놓는다. 그다음에 다음과 같이 동전을 움직인다.
- 동전이 있는 곳에 쓰여 있는 숫자 X를 본다.
- 위, 아래, 왼쪽, 오른쪽 방향 중에 한가지를 고른다.
- 동전을 위에서 고른 방향으로 X만큼 움직인다. 이때, 중간에 있는 구멍은 무시한다. 만약 동전이 구멍에 빠지거나, 보드의 바깥으로 나간다면 게임은 종료된다. 형택이는 이 재밌는 게임을 되도록이면 오래 하고 싶다. 보드의 상태가 주어졌을 때, 형택이가 최대 몇 번 동전을 움직일 수 있는지 구하는 프로그램을 작성하시오.
입력
줄에 보드의 세로 크기 N과 가로 크기 M이 주어진다. 이 값은 모두 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 보드의 상태가 주어진다. 쓰여 있는 숫자는 1부터 9까지의 자연수 또는 H이다. 가장 왼쪽 위칸은 H가 아니다. H는 구멍이다.
1
2
3
4
3 7
3942178
1234567
9123532
1
2
3
4
3 7
2H9HH11
HHHHH11
9HHHH11
출력
첫째 줄에 문제의 정답을 출력한다. 만약 형택이가 동전을 무한번 움직일 수 있다면 -1을 출력한다.
1
5
1
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
28
29
30
import sys
sys.setrecursionlimit(10000) # Recursive Depth 늘려줌
N, M = map(int, input().strip().split())
board = [
list(map(lambda x: int(x) if x.isnumeric() else x, input().strip()))
for _ in range(N)]
history = [] # 무한 루프 방지를 위해 이전 경로 기억
def dfs(count, i, j):
if [i, j] in history:
return -1
else:
if 0<= i < N and 0<= j < M and board[i][j] != 'H':
#밖이나 구멍으로 떨어지지 않은 경우
move = board[i][j]
res = []
for idx in [[i+move, j], [i-move, j], [i, j+move], [i, j-move]]: #상하좌우
history.append([i, j])
res.append(dfs(count+1, *idx))
history.pop()
if -1 in res:
return -1
else:
return max(res)
else:
return count
print(dfs(0, 0, 0))
근데 무슨 짓을 해도 시간초과라 구글링 해보니 Dynamic Programming을 해야한다더라. 그래서 관련 글들 찾아보고 Memoization를 사용해서 풀었다.
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
29
30
31
32
33
34
35
36
37
38
import sys
sys.setrecursionlimit(10000)
input = sys.stdin.readline
N, M = map(int, input().strip().split())
board = [
list(map(lambda x: int(x) if x.isnumeric() else x, input().strip()))
for _ in range(N)]
memo = [[-1] * M for _ in range(N)] # dp를 위한 Memoization
history = []
def dfs(count, i, j):
if [i, j] in history:
memo[i][j] = "inf"
else:
if (
0 <= i < N
and 0 <= j < M
and board[i][j] != "H"
and memo[i][j] != "inf" #무한 루프가 발견되면 더 할 필요 없음
and count > memo[i][j]
):
memo[i][j] = count
move = board[i][j]
for idx in [[i + move, j], [i - move, j], [i, j + move], [i, j - move]]:
history.append([i, j])
dfs(count + 1, *idx)
history.pop()
dfs(0, 0, 0)
# 결과 출력
flat = [col for row in memo for col in row]
if "inf" in flat:
print(-1)
else:
print(max(flat) + 1)
Leave a comment