마리오 파티
문제

일렬로 된 보드가 있다. 맨 왼쪽은 시작점이고, 맨 오른쪽에는 별이 있다. 매 턴마다 플레이어는 1부터 S까지의 자연수가 균일한 확률로 나오는 주사위를 굴린 뒤 나온 수만큼 앞으로 이동한다. 플레이어가 멈춘 칸에는 숫자가 쓰여 있는데, 거기에 쓰인 만큼 (양수일 때) 코인을 얻거나 (음수일 때) 잃는다. T턴이 지나면 게임이 종료된다.
예를 들어 보드가 위와 같고, S=4, T=5라고 하자. 주사위를 굴려서 2, 3, 4, 1, 1이 나오면 총 수익은 170코인이 된다. 반면 주사위를 굴려서 1, 3, 2, 4, 1이 나오면 총 수익은 220코인이 된다. 꼭 별이 있는 칸에 정확히 멈출 필요는 없다. 별이 있는 칸을 지나가면 별을 얻을 수 있기 때문이다.
보드가 안 좋아서 총 수익이 음수가 되어야만 별을 얻을 수도 있다. 아래 보드 (S=4, T=5)의 경우 별을 얻을 때의 최대 수익은 -100코인이다. 하지만 별을 많이 얻는 것이 중요하기 때문에, 플레이어는 코인을 잃는 한이 있어도 별을 얻고 싶어한다.

T턴 이내에 별을 얻고자 할 때, 최대 수익은 얼마일까?
입력
입력은 20개 이하의 테스트케이스로 구성되어 있고, 맨 끝에 0이 온다. 각 테스트케이스의 첫 줄에는 N (출발점과 별 사이의 칸 수), S, T가 주어진다. 2 ≤ N ≤ 200, 2 ≤ S ≤ 10, N + 1 ≤ ST, T ≤ N + 1이다. 따라서 T턴 이내에 별을 먹는 방법이 꼭 존재한다.
첫 줄 다음에는 여러 줄에 걸쳐 N개의 정수가 주어진다. 각 칸에 도착할 때 얻거나 잃는 코인의 수를 나타낸다. 이 값의 절댓값은 10000보다 작다.
출력
각 테스트케이스에 대해 T턴 이내에 별을 얻을 때의 최대 수익을 출력한다.
바쁜 프로젝트때문에 오랜만에 문제를 풀었다.
해당 문제는 다이나믹 프로그래밍 DP 문제였다.
이 레벨의 문제는 역시 2차원 dp를 사용
자주 사용하는 총 횟수와 이동거리를 dp로 만들어서 사용하는 방법.
이동할 수 있는 만큼 비교하면서 움직이고 다음 차례로 이동하면서 반복하는 방식
import sys
input = sys.stdin.readline
while 1:
input_list = list(map(int,input().split()))
# 종료
if input_list[0] == 0:
break
N, S, T = input_list[0], input_list[1], input_list[2]
board = []
# 보드 입력
while len(board) < N:
board.extend(list(map(int,input().split())))
INF = -987654321
# N 개와 마지막 칸 (N+1)
# 총 횟수인 T 만큼
dp = [[INF] * (N+1) for _ in range(T)]
# 처음 초기화
# 처음 움직일 수 있는 칸만큼
for i in range(S):
dp[0][i] = board[i]
# T-1까지
for i in range(T-1):
for j in range(N):
# INF 아니면 올 수 있다는 것
if dp[i][j] != INF:
# 해당 자리에서 S만큼 움직이는 것
for k in range(1,S+1):
# 마지막 칸을 넘으면 마지막 칸에
if j + k >= N:
if dp[i+1][N] < dp[i][j]:
dp[i+1][N] = dp[i][j]
# 아니면
# 해당 자리와 현재 자리 + 보드의 별수를 비교
else:
if dp[i+1][j+k] < dp[i][j] + board[j+k]:
dp[i+1][j+k] = dp[i][j] + board[j+k]
print(dp[-1][-1])
'@@@ 알고리즘 > 백준 스터디' 카테고리의 다른 글
백준 4658(삼각형 게임) - 해결 (0) | 2022.02.21 |
---|---|
백준 1719(택배) - 참고 해결 (0) | 2022.02.19 |
백준 3649(로봇 프로젝트) - 해결(python) (0) | 2022.02.06 |
백준 21922(학부 연구생 민상) - 해결(pypy) (0) | 2022.02.06 |
백준 1490(자리수로 나누기) - 해결 (0) | 2022.02.06 |