🐻作者: 芝士小熊饼干
📖 系列专栏: 数据结构-蓝桥杯-算法⭐
💪坚持天数:9天🤖
背包问题01 ⭐
有N件物品和一个容量是V的背包。每件物品只能使用一次
第件物品的体积是v,价值是wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大.
输出最大价值。
输入格式
第一行两个整数,N,,用空格隔开,分别表示物品数量和背包容积接下来有行,每行两个整数,w,用空格隔开,分别表示第件物品的体积和价值
输出格式
输出一个整数,表示最大价值输入样例
4 5 1 2 2 4 3 4 4 5
输出样例:
8
问题分析 ⭐
⭐
背包问题是一个经典的动态规划问题,我们假设有一个背包和一些物品,背包的容量为C,每个物品有一个重量w和一个价值v,我们需要将物品放进背包中使得放入的物品价值之和最大。
假设用dp[i][j]表示前i个物品放入容量为j的背包中所能得到的最大价值,那么状态转移方程为:
当j<w[i]时:dp[i][j]=dp[i-1][j]
当j>=w[i]时:dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])其中,dp[i-1][j]表示不放第i个物品,dp[i-1][j-w[i]]+v[i]表示放第i个物品。
最后,dp[n][C]即为所求,其中n表示物品的个数。
如果需要求出具体的物品放入方案,可以在状态转移过程中记录每一个状态的来源,从而得到最优方案
dp[i-1][j]--->不选
dp[i-1][j-vlist[i]]+wlist[i]---->选那个物品:选了该物体后剩余空间最大价值+该物体最大价值
N,V=map(int,input().split())
vlist,wlist=[0],[0]# vilst物品体积,wlist物品价值
for i in range(N):
tmp=list(map(int,input().split()))
vlist.append(tmp[0])
wlist.append(tmp[1])
# 创建dp表
dp=[[0 for i in range(V+1)] for i in range(N+1)]
# vlist.insert(0,0)
# wlist.insert(0,0)
for i in range(1,N+1):
for j in range(1,V+1):
if (vlist[i]<=j):
dp[i][j]=max(dp[i-1][j],dp[i-1][j-vlist[i]]+wlist[i])
else:
dp[i][j]=dp[i-1][j]
print('最大价值为',dp[N][V])
背包问题01-空间优化⭐
N,V=map(int,input().split())
vlist,wlist=[0],[0]# vilst物品体积,wlist物品价值
for i in range(N):
tmp=list(map(int,input().split()))
vlist.append(tmp[0])
wlist.append(tmp[1])
# 创建dp表
dp=[0 for i in range(V+1)]
# vlist.insert(0,0)
# wlist.insert(0,0)
for i in range(1,N+1):
for j in range(V,0,-1):
if (vlist[i]<=j):
dp[j]=max(dp[j],dp[j-vlist[i]]+wlist[i])
print('最大价值为',dp[V])
转化成一维空间,从右向左计算
总结动态规划模板
def dpFunction(params): # 初始化 DP table dp = [[0] * n for _ in range(m)] # 初始化第一行和第一列的边界条件 for i in range(n): dp[0][i] = ... for i in range(m): dp[i][0] = ... # 填充 DP table for i in range(1, m): for j in range(1, n): dp[i][j] = ... # 返回最终结果 return dp[m-1][n-1]
其中,
m
和n
是问题所涉及的状态数或数组大小。在填充 DP table 时,通常需要进行一些状态转移方程的计算。也可以通过调整边界条件等方法来实现不同的具体问题。