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

     版权所有,欢迎转载,但是转载请注明出处:潇一

原文地址:https://www.cnblogs.com/xiaoyi115/p/3178766.html