1757번: 달려달려
어제, 그리고 어제 어제 단체달리기를 두 번이나 하였다. 원장선생님의 이러한 하드 트레이닝으로 월드 학생들의 체력은 거의 박지성 수준이 되었다. 그래서 월드 학생들은 운동장을 도는데 정
www.acmicpc.net
아이디어:
DP를 구성하는 방법을 떠올리는 방식이 어렵다.
조건
- 1분을 달리면 지침 지수는 1이 올라간다. 1분을 쉬면 지침 지수는 1 내려간다. -> 지침지수가 0일 때 쉬어도 그대로 0이다.
- 쉬기 시작하면 지침지수가 0이 되기 전에는 다시 달릴 수 없다.
- 달리기가 끝나면 지침지수는 0이 되어야 한다. -> 마지막 n분째에는 달릴 수 없다.
DP[x][y][z] = x초에 y의 지침지수를 가지고 z는 뛰고 있는지 여부를 나타낼 때 달린 겨리의 최댓값 저장
- j가 1, 0이 아닐 떄:
dp[i][j][1] = dp[i-1][j-1][1] + D[i] #1,0이 아니므로 dp[i-1][j-1][0]인 경우는 고려하지 않음
dp[i][j][0] = max(dp[i-1][j-1][1], dp[i-1][j+1][0])
- j가 0일 때 : 쉬어도 지침 지수가 그대로 0
dp[i][j][0] = max(dp[i-1][j+1][0], dp[i-1][j+1][1], dp[i-1][j][[0]) #j가 0이므로 dp[i][j][1]은 불가능
- j가 1일 때 : 쉬다가 달리는 것이 가능
dp[i][j][1] = max(dp[i-1][j-1][1], dp[i-1][j-1][0]) + D[i]
dp[i][j][0] = max(dp[i-1][j+1][1], dp[i-1][j+1][0])
최대로 멀리 갈 수 있는 거리를 구해야 하므로, dp[n][0][0]을 출력하면 된다.(지침지수 0이려면 마지막에 쉬어야 하니까)
※파이썬에서 3중 배열 선언
dp = [[[0]*2 for _ in range(m+5)] for _ range(n+5)]
#파이썬으로 제출하면 메모리 초과 나서 C++로 제출함.
import sys
n, m = map(int, sys.stdin.readline().split())
dp = [[[0]*2 for _ in range(m+5)] for _ in range(n+5)]
D = [0]*(n+1)
for i in range(1,n+1):
D[i]=int(sys.stdin.readline())
for i in range(1,n+1):
for j in range(m+1):
if j != 1:
if j: #j가 1,0이 아닐때
dp[i][j][1] = dp[i-1][j-1][1] + D[i]
dp[i][j][0] = max(dp[i-1][j+1][1], dp[i-1][j+1][0])
else: #j가 0일때
dp[i][j][0] = max(dp[i-1][j+1][0], dp[i-1][j+1][1], dp[i-1][j][0])
else: #j가 1일때
dp[i][j][1] = max(dp[i-1][j-1][1], dp[i-1][j-1][0]) + D[i]
dp[i][j][0] = max(dp[i-1][j+1][1], dp[i-1][j+1][0])
print(dp[n][0][0])
DP배열 선언 할 때 dp = [[[0]*2 for _ in range(m+1)] for _ range(n+1)] 로 했더니 out of index -> j+1을 계산하는 경우를 생각하지 못해서
그 외에도 인덱스 때문에 자잘한 오류가 있었다. 여러번 다시 풀어봐야 할 유형인 것 같다.
'알고리즘💻 > DP' 카테고리의 다른 글
BOJ 14494번: 다이나믹이 뭐예요? (0) | 2021.01.24 |
---|---|
BOJ 20500번: Ezreal 여눈부터 가네 ㅈㅈ (0) | 2021.01.24 |
BOJ 1463번: 1로 만들기 (0) | 2021.01.24 |
BOJ 15988번: 1, 2, 3 더하기 3 (0) | 2021.01.24 |
BOJ 2748번: 피보나치 수 2 (0) | 2021.01.24 |