处理何种问题:给定 n 种物品(每种类型无限)和一个容量为 V 的背包,物品 i 的体积为 vi,其价 值为 pi,求其最终可以装进背包的物品最大价值。
性能:时间复杂度为O(nV)。
原理:在学习背包之前,可能是思考方向的不对的原因,导致对背包题解的做法有些误解,现在借着写完全背包我在这里阐述一下我对于背包的理解。
在此,我先假定一个数组dp[V],里面存的是当背包容量只有V的情况下,可以存的物品的最大价值是多少。然后,我们假设只有第一件物品arr[0],然后我们利用arr[0],对dp[V]进行赋值操作,如下图所示:
dp[0] |
… |
dp[arr[0].v] |
dp[arr[0].v+1] |
… |
dp[arr[0].v*2] |
… |
dp[V] |
0 |
… |
arr[0].p |
arr[0].p |
… |
arr[0].p*2 |
… |
V/arr[0].v*arr[i].p |
然后,我在dp[V]已更新的基础上我们再加上一个物品arr[1],对此我们依旧仿照上面的操作判断dp[V]=max(dp[V],dp[V-arr[1].v]+arr[1].p),毕竟我们只需要确保当背包为V时,看看怎么加物品i使得dp[V]最大(是放还是不放),这是一个迭代的过程,dp[V-arr[1].v]+arr[1].p就是为了得到在放该物品之后能得到的最大值。
在捋清思路之后,完全背包的解法就是这么显得顺其自然,很像贪心。
实现步骤:与01背包类似,具体看代码。
备注:状态转移方程具体看代码,个人觉得与01背包相似,但又有一些根本上的不同,在这里就不写了。
输入样例解释:
5 1000 //n种物品,背包容量为V
144 990//第0种物品的体积和价值
487 436
210 673
567 58
1056 897
输出样例解释:
5940 //最大价值
#include<iostream> #include<cstdio> #include<string.h> #include<algorithm> using namespace std; struct node { int v,p; }; node arr[11000]; int dp[100010]; int main() { int n,V; memset(dp,0,sizeof(dp)); scanf("%d%d",&n,&V); for(int i=0;i<n;++i) scanf("%d%d",&arr[i].v,&arr[i].p); for(int i=0;i<n;++i) { for(int j=arr[i].v;j<=V;++j) { dp[j]=max(dp[j],dp[j-arr[i].v]+arr[i].p); } } printf("%d ",dp[V]); return 0; }