0-1背包问题详解二(完全背包问题)
问题描述
给定n种物品和一个背包。物品i的重量是w(i),其价值为v(i),背包的容量为c(即最多能够装c重量的物品)。这n种物品可以重复放置(这是与普通背包问题的不同之处)。普通背包问题
输入n=5,c=6.物品容量和价值分别为:
2 6
2 3
6 5
5 4
4 6
最后输出时:18
问题求解:
f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0<=k*c[i]<=v}
似乎利用上面那个公式就可以很好的求出解。
这里给出另外一组公式,该公式和上文的公式是一样的,只是第二个for语句的倒过来。
for i=1..N
for v=0..V
f[v]=max{f[v],f[v-cost]+weight}
为什么这样一改就可行呢?首先想想为什么上文中要按照v=V..0的逆序来循环。这是因为要保证第i次循环中
的状态f[i][v]是由状态f[i-1][v-c[i]]递推而来。换句话说,这正是为了保证每件物品只选
一次,保证在考虑“选入第i件物品”这件策略时,依据的是一个绝无已经选入第i件物品
的子结果f[i-1][v-c[i]]。而现在完全背包的特点恰是每种物品可选无限件,所以在考
虑“加选一件第i种物品”这种策略时,却正需要一个可能已选入第i种物品的子结果f[i][vc[
i]],所以就可以并且必须采用v=0..V的顺序循环。这就是这个简单的程序为何成立的
道理。
1 void compelteKnapsack(){ 2 int c,n; 3 cout<<"请输入最大容量,小于100"<<endl; 4 cin>>c; 5 cout<<"请输入背包个数"<<endl; 6 cin>>n; 7 cout<<"请输入各个背包重量和价值"<<endl; 8 for(int i=1;i<=n;i++){ 9 cin>>w[i]>>v[i]; 10 } 11 for(int i=0;i<=n;i++) 12 p[i]=0; 13 for(int i=1;i<=n;i++) 14 for(int j=w[i];j<=c;j++) 15 p[j]=max(p[j],p[j-w[i]]+v[i]); 16 cout<<"结果是"<<p[c]<<endl; 17 }
View Code
版权所有,欢迎转载,但是转载请注明出处:潇一