背包问题

读《背包九讲》的几点感受,这里mark一下。

a.01背包问题题目描述:

  有N件物品和一个容量为V 的背包。放入第i件物品耗费的空间是Ci,得到的价值是Wi。求解将哪些物品装入背包可使价值总和最大。

 该问题的解决的一般思路是:写状态转移方程、动态规划。

   

 具体实现的伪代码如下:

     

  我们可以观察到上述伪码的时间复杂度和空间复杂度都是O(NV),对于时间复杂度暂时没有好的方法优化,但是空间复杂度却可以降低到O(V).

       

  为什么把第二次循环掉个头,就可以用一维的F[]就能实现了?

  其中“刚好装满”的例题:

POJ 3624   Charm Bracelet

 1 #include <iostream>
 2 #include <cmath>
 3 #include <cstring>
 4 using namespace std;
 5 
 6 struct data{
 7     int weight ;   //重量 
 8     int value ;    //价值 
 9 };
10 
11 int main(){
12     int num;       //物品个数 
13     int maxm;      //最大能承受重量 
14     cin>>num>>maxm; 
15     data pack[num+1];    
16     for(int i=1;i<=num;i++){    //输入数据 
17         cin>>pack[i].weight ;     
18         cin>>pack[i].value ;
19     }    
20     
21     int result[maxm+1];  //初始化为0;  
22     memset(result,0,sizeof(result));
23     
24     for(int i=1;i<=num;i++){  
25         for(int v=maxm;v>=pack[i].weight;v--)
26         {                                      
27                 result[v]=max( result[v],   result[v-pack[i].weight]+pack[i].value );                
28         }      
29     } 
30     cout<<result[maxm]<<endl;
31 } 
View Code

 

b.完全背包问题题目描述:

      有N种物品和一个容量为V 的背包,每种物品都有无限件可用。放入第i种物品的耗费的空间是Ci,得到的价值是Wi。求解:将哪些物品装入背包,可使这些物品的耗费的空间总和不超过背包容量,且价值总和最大。

  这里给出一个解决方案的伪码。仔细观察可以发现,这个和01背包问题的区别仅仅是第二个for循环遍历的方向不同而已,这就实现了可以取无限件。“看似困难的问题,却存在着巧妙而简单的的解决方法”,也许这正是算法的妙处。下面来解释这到底为什么:

这里曝上一道完全背包的问题,直接套用上面的伪码即可:

POJ 1384   Piggy-Bank

 1 //我的代码
 2 #include <stdio.h>
 3 #include <string.h>
 4 const int num=501,oo=1000000000;
 5 int f[10001]={0},p[num],w[num];
 6 int main()
 7 { 
 8     int t,n,weight_e,weight_f,i,j,weightpig;
 9     scanf("%d",&t);
10     while (t--){
11 
12         scanf("%d%d",&weight_e,&weight_f);
13         for (i=1;i<=weight_f;i++) f[i]=oo;
14         weightpig=weight_f-weight_e;
15         scanf("%d",&n);
16         for (i=1;i<=n;i++) 
17             scanf("%d%d",&p[i],&w[i]);
18         
19         for (i=1;i<=n;i++){
20             for (j=w[i];j<=weightpig;j++){
21                 if (f[j-w[i]]+p[i]<f[j]) f[j]=f[j-w[i]]+p[i];    
22             }
23         }
24             
25         if (f[weightpig]==oo){
26              printf("This is impossible.\n");    
27         }
28         else{
29              printf("The minimum amount of money in the piggy-bank is %d.\n",f[weightpig]);    
30         } 
31     }
32 }
View Code

 

posted on 2015-11-11 00:19  逸阳  阅读(227)  评论(0编辑  收藏  举报

导航