0-1背包 卡码网第46题:
二维dp:
def Knapsack(m,n,materials, values):
#dp[i][j]表示总重为i的背包,选前j个物品的最大价值
dp = [[0] * (m+1) for _ in range(n + 1)]
for i in range(1, n + 1):
for j in range(1, m + 1):
if materials[j - 1] <= i:
dp[i][j] = max(dp[i][j - 1], dp[i - materials[j - 1]][j - 1] + values[j - 1])
else:
dp[i][j] = dp[i][j - 1]
return dp[n][m]
if __name__ == '__main__':
m, n = map(int, input().strip().split())
materials = list(map(int, input().strip().split()))
values = list(map(int, input().strip().split()))
print(Knapsack(m, n, materials, values))
看题解之后发现i、j是反的,其实不影响题目AC,但是为了更深入学习背包问题,这里把i、j反过来一下重写;
def Knapsack(m,n,materials, values):
#dp[i][j]表示总重为j的背包,选前i个物品的最大价值
dp = [[0] * (n+1) for _ in range(m)]
for _ in range(n + 1):
if _ >= materials[0]:
dp[0][_] = values[0]
for i in range(1,m):
for j in range(1, n + 1):
if j >= materials[i]:
dp[i][j] = max(dp[i - 1][j - materials[i]] + values[i], dp[i - 1][j])
else:
dp[i][j] = dp[i - 1][j]
return dp[m - 1][n]
if __name__ == '__main__':
m, n = map(int, input().strip().split())
materials = list(map(int, input().strip().split()))
values = list(map(int, input().strip().split()))
print(Knapsack(m, n, materials, values))
一维dp:
def Knapsack(m,n,materials, values):
dp = [0] * (n + 1)
for i in range(m):
for j in range(n, materials[i] - 1, -1):
dp[j] = max(dp[j], dp[j - materials[i]] + values[i])
return dp[n]
if __name__ == '__main__':
m, n = map(int, input().strip().split())
materials = list(map(int, input().strip().split()))
values = list(map(int, input().strip().split()))
print(Knapsack(m, n, materials, values))
416. 分割等和子集
抽象成0-1背包,nums[i]既是重量也是价值。
class Solution:
def canPartition(self, nums: List[int]) -> bool:
s = sum(nums)
length = len(nums)
if s & 1: return False
else:
target = s >> 1
dp = [0] * (target + 1)
for i in range(length):
for j in range(target, nums[i] - 1, -1):
dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])
return dp[target] == target
今日总结:
初学0-1背包。