https://www.acmicpc.net/problem/12865
12865번: 평범한 배낭
첫 줄에 물품의 수 N(1 ≤ N ≤ 100)과 준서가 버틸 수 있는 무게 K(1 ≤ K ≤ 100,000)가 주어진다. 두 번째 줄부터 N개의 줄에 거쳐 각 물건의 무게 W(1 ≤ W ≤ 100,000)와 해당 물건의 가치 V(0 ≤ V ≤ 1,000)
www.acmicpc.net
KnapSack (냅색) 문제
냅색 알고리즘은 담을 수 있는 물건이 나눌 수 있냐 없냐에 따라 나뉜다.
담을 수 있는 물건이 나누어 질 때(설탕 몇 g 등): 분할가능 배낭문제(Fractional Knapsack Problem)
담을 수 있는 물건이 나누어 질 수 없을 때(담는다 or 안담는다): 0-1 배낭문제(0-1Knapsack Problem)
해당 문제는 나누어 지지 않는 문제로 0-1 배낭 문제이다.
Solution #1
def main(n,m,w_val):
dp = [[0 for _ in range(m+1)] for _ in range(n+1)]
# w_val.sort(key = lambda x: (x[0],x[1]))
for i in range(n+1): # 물품 수만큼(행)
for j in range(m+1): # 배낭 최대 무게(열)
if i==0 or j==0:
dp[i][j] = 0
elif w_val[i-1][0] <= j: # 현재 물품 무게 <= 배낭 최대 무게
# max(현재 물품의 가치 + dp[이전 물품][배낭 최대 무게(j)-현재 물품 무게]
# w_val[i-1][0] 무게 / w_val[i-1][1] 가치
dp[i][j] = max(w_val[i-1][1]+dp[i-1][j-w_val[i-1][0]],dp[i-1][j])
else: # 현재 물품 무게 > 배낭 최대 무게
dp[i][j] = dp[i-1][j] # 해당 배낭 최대 무게(j)에서 이전 물품까지 최대 가치 합 가져옴.
return dp[n][m]
n, m = map(int, input().split())
w_val = []
for i in range(n):
w, v = map(int, input().split())
w_val.append([w,v])
print(main(n,m,w_val))
dp 결과는 아래와 같다.
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 6 | 6 | 6 | 6 | 6 |
0 | 0 | 0 | 6 | 8 | 8 | 8 | 14 |
0 | 0 | 0 | 6 | 8 | 12 | 12 | 14 |
0 | 0 | 0 | 6 | 8 | 12 | 13 | 14 |
weight_value 리스트를 굳이 정렬하지 않았음에도 무게에 따라 정렬되어(행) dp 결과가 저장된 것을 확인할 수 있다.
Solution #2
n, m = map(int, input().split())
w_val = [[0, 0]]
dp = [[0 for _ in range (m + 1)] for _ in range(n + 1)]
for _ in range(n):
w_val.append(list(map(int, input().split())))
# 냅색 문제 풀이
for i in range(1, n + 1):
for j in range(1, m + 1):
weight = w_val[i][0]
value = w_val[i][1]
if j < weight:
dp[i][j] = dp[i - 1][j] # weight보다 작으면 위의 값을 그대로 가져온다
else:
dp[i][j] = max(value + dp[i - 1][j - weight], dp[i - 1][j])
print(dp[n][m])
Solution #1 과 같은 동일한 문제 풀이지만, dp 결과가 다른 방식으로 저장되는 코드이다.
Solution #2 의 dp 결과는 아래와 같다.
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ||
weight | value | ||||||||
6 | 13 | 0 | 0 | 0 | 0 | 0 | 13 | 13 | |
4 | 8 | 0 | 0 | 0 | 8 | 8 | 13 | 13 | |
3 | 6 | 0 | 0 | 6 | 8 | 8 | 13 | 14 | |
5 | 12 | 0 | 0 | 6 | 8 | 12 | 13 | 14 |
Reference
https://gsmesie692.tistory.com/113
'Programming > DP' 카테고리의 다른 글
Baekjoon / 소형기관차 (0) | 2022.03.22 |
---|---|
Baekjoon / 계단오르기 (0) | 2022.03.08 |
Baekjoon / 다익스트라 알고리즘 / 최단 경로 (0) | 2022.02.14 |
Baekjoon / DP / 포도주 시식 (0) | 2022.02.12 |
Baekjoon / DP / 설탕 배달 (0) | 2022.02.12 |