| 가방 크기 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 루비 | 0 | 0 | 0 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 |
| 다이아 | 0 | 0 | 0 | 6 | 6 | 6 | 6 | 9 | 9 | 9 | 9 | 9 | 9 |
| 사파이어 | 0 | 0 | 0 | 6 | 6 | 6 | 6 | 9 | 11 | 11 | 11 | 11 | 11 |
💎 루비를 선택하는 경우(dp[루비])
💎 다이아를 선택하는 경우
(dp[다이아] = 각 무게별로 [루비, 다이아]에서 만들어낼 수 있는 최대 가치합)
💎 사파이어를 선택하는 경우
(dp[사파이어] = 각 무게별로 [루비, 다이아, 사파이어]에서 만들어낼 수 있는 최대 가치합)
현재 내가 구하려고 하는 셀의 값은
MAX(현재 보석의 가치+남은가방크기만큼 나머지 보석을 넣을 때 최대 가치, 이전까지 구해둔 보석의 가치)
즉,
ans[i][j] = max(profit[i] + ans[i-1][j-weight[i], ans[i-1][j]]
n, k = map(int, input().split())
weight = [0]
value = [0]
for i in range(n):
w, v = map(int, input().split())
weight.append(w)
value.append(v)
dp = [[0] * (k+1) for i in range(n+1)]
# dp 리스트 채우기
for i in range(n+1):
for j in range(1, k+1):
if weight[i] <= j:
dp[i][j] = max(value[i] + dp[i-1][j-weight[i]], dp[i-1][j])
else:
dp[i][j] = dp[i-1][j]
# 최종 답
answer = max(dp[n-1])
print(answer)
도무지 모르겠어서 풀이 참고 사이트 를 참고했다.
dp[i] = i요소를 반드시 포함하는 경우의 최대 가치의 합 까지는 알고리즘을 떠올려봤는데, [루비] → [루비, 다이아] → [루비, 다이아, 사파이어] 이런식으로 요소들을 누적시켜서 계산할 생각은 못했다. (그게 바로 DP의 핵심인데 왜 못떠올렸을까...)
처음엔 n행은 0-based로, k열은 1-based로 설정하였다. 그래서 dp[0][]을 초기화한 후 dp[1][]부터 순회하도록 구현했다. 그러나 행또한 1-based로 하면 굳이 초기화 코드가 없어도 된다는걸 깨닫고 행과 열 모두 1-based로 수정했다.