zoukankan      html  css  js  c++  java
  • 背包问题

    读《背包九讲》的几点感受,这里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.
    ");    
    27         }
    28         else{
    29              printf("The minimum amount of money in the piggy-bank is %d.
    ",f[weightpig]);    
    30         } 
    31     }
    32 }
    View Code
  • 相关阅读:
    Uva 1636 决斗
    数论初步
    Gym 100169A 最短路
    Uva 12169 不爽的裁判 模运算
    Uva 11582 巨大的斐波那契数 模运算
    Uva 10791 最小公倍数的最小和 唯一分解定理
    Uva 10375 选择与除法 唯一分解定理
    poj 3485 区间选点
    第二届团体程序设计天梯赛
    Uva 12657 双向链表
  • 原文地址:https://www.cnblogs.com/liugl7/p/4954985.html
Copyright © 2011-2022 走看看