关闭

HDU_Steps3.3 各种背包 HDU1114 HDU1171 HDU2191 HDU2955 HDU3496 HDU2546 HDU1203 HDU3466

标签: 背包动态规划
749人阅读 评论(0) 收藏 举报
分类:

转自:http://blog.csdn.net/swm8023/article/details/6762190

背包总结,收藏之。


HDU_STEPS3.3 主要是背包问题


3.3.1 HDU1114 Piggy-Bank 完全背包,要正好装满

  1. #include <cstdio>  
  2. #include <string.h>  
  3. using namespace std;  
  4. int e,f,n;  
  5. int d[10005];  
  6. int p[505],w[505];  
  7. int main(){  
  8.     int cas;  
  9.     scanf("%d",&cas);  
  10.     while(cas--){  
  11.         scanf("%d%d",&e,&f);  
  12.         e=f-e;  
  13.         scanf("%d",&n);  
  14.         for(int i=1;i<=n;i++)scanf("%d%d",&p[i],&w[i]);  
  15.           
  16.         //DP  
  17.         for(int i=1;i<=e;i++)d[i]=1e9;  
  18.         d[0]=0;  
  19.         for(int i=1;i<=n;i++){  
  20.             for(int j=w[i];j<=e;j++){  
  21.                 if(d[j-w[i]]+p[i]<d[j])d[j]=d[j-w[i]]+p[i];        
  22.             }     
  23.         }   
  24.           
  25.         if(d[e]==1e9)printf("This is impossible.\n");  
  26.         else printf("The minimum amount of money in the piggy-bank is %d.\n",d[e]);  
  27.     }  
  28.   
  29.     return 0;     
  30. }   

3.3.2 HDU1171 Big Event in HDU 

多重背包,每种物品个数有限制,用一个数组标记该值是否可达

最后从中间像两边扫描,先找到的值为A和B中的一个

  1. #include <cstdio>  
  2. #include <string.h>  
  3. using namespace std;  
  4. int n,tot;   
  5. int v[55],m[55];  
  6. bool d[250005];   
  7. int main(){  
  8.     while(scanf("%d",&n)&&n>=0){  
  9.         int tot=0;  
  10.         for(int i=1;i<=n;i++){  
  11.             scanf("%d%d",&v[i],&m[i]);   
  12.             tot+=v[i]*m[i];  
  13.         }  
  14.           
  15.         //多重背包 每种物品数目固定 DP   
  16.         memset(d,0,sizeof d);  
  17.         d[0]=true;  
  18.         for(int i=1;i<=n;i++){  
  19.             for(int k=1;k<=m[i];k++){  
  20.                 for(int j=tot;j>=v[i];j--){  
  21.                     if(d[j-v[i]])d[j]=true;       
  22.                 }     
  23.             }     
  24.         }     
  25.         //输出答案   
  26.         int ind=0;  
  27.         for(int i=tot/2,j=tot/2;;i++,j--){  
  28.             if(d[i]){ind=i;break;}  
  29.             if(d[j]){ind=j;break;}    
  30.         }  
  31.         if(ind<tot-ind)ind=tot-ind;  
  32.         printf("%d %d\n",ind,tot-ind);  
  33.     }   
  34.     return 0;     
  35. }  

3.3.3 HDU2191 悼念512汶川地震

多重背包,跟新某一点时选择价值更大的组合

  1. memset(d,-1,sizeof d);  
  2. d[0]=0;  
  3. for(int i=1;i<=m;i++){  
  4.     for(int j=1;j<=c[i];j++){  
  5.         for(int k=n;k>=p[i];k--){  
  6.             if(d[k-p[i]]!=-1&&d[k-p[i]]+h[i]>d[k]){  
  7.                 d[k]=d[k-p[i]]+h[i];      
  8.             }  
  9.         }     
  10.     }  
  11. }  

3.3.4 HDU2955 Robberies 

题目看了半天才看懂,就是求小偷最多能偷几个银行,DP使该点不被捉的概率最大

假如偷了N个银行,被捉概率是p1,p2..pn ,则不被捉的概率是(1-p1)(1-p2)...(1-pn)

  1. #include <cstdio>  
  2. using namespace std;  
  3. int cas,mi[101],n,tot;  
  4. double pi[101],p;  
  5.   
  6. double d[10000];  
  7. int main(){  
  8.     scanf("%d",&cas);  
  9.     while(cas--){  
  10.         for(int i=0;i<=10000;i++)d[i]=0;  
  11.         tot=0;  
  12.         d[0]=1;   
  13.           
  14.         scanf("%lf%d",&p,&n);  
  15.         for(int i=1;i<=n;i++){  
  16.             scanf("%d%lf",&mi[i],&pi[i]);  
  17.             tot+=mi[i];   
  18.         }  
  19.         //背包 转换为乘法 使同一个点不被捉的概率最大   
  20.         for(int i=1;i<=n;i++){  
  21.             for(int j=tot;j>=mi[i];j--){  
  22.                 if(d[j]<d[j-mi[i]]*(1-pi[i]))d[j]=d[j-mi[i]]*(1-pi[i]);  
  23.             }  
  24.         }  
  25.           
  26.         for(int i=tot;i>=0;i--){  
  27.             if(d[i]>=1-p){printf("%d\n",i);break;}     
  28.         }  
  29.     }  
  30.       
  31.     return 0;     
  32. }  

3.3.5 HDU3496 Watch the Movie

二维背包,背包中的物品个数有限制

状态表示为d[n][m],n为使用物品的个数,m为背包中物品的个数

注意循环的方向,要保证d[n][m]中有m件物品,最后d[N][M]即为所求

  1. #include <cstdio>  
  2. #include <string>  
  3. #include <math.h>  
  4. #include <string.h>  
  5. #include <stdlib.h>  
  6. #include <iostream>  
  7. #include <algorithm>  
  8. using namespace std;  
  9.   
  10. int cas,n,m,l;   
  11. int w[105],v[105],d[105][1005];  
  12. int main(){  
  13.     scanf("%d",&cas);  
  14.     while(cas--){  
  15.         scanf("%d%d%d",&n,&m,&l);  
  16.         for(int i=1;i<=n;i++)scanf("%d%d",&w[i],&v[i]);  
  17.           
  18.         //DP  
  19.         memset(d,-1,sizeof d);  
  20.         d[0][0]=0;  
  21.         for(int i=1;i<=n;i++){  
  22.             for(int j=m;j>=1;j--){//注意方向,很重要   
  23.                 for(int k=l;k>=w[i];k--){  
  24.                     if(d[j-1][k-w[i]]!=-1)d[j][k]=max(d[j][k],d[j-1][k-w[i]]+v[i]);   
  25.                 }     
  26.             }     
  27.         }  
  28.           
  29.         int r=0;  
  30.         for(int i=1;i<=l;i++)r=max(r,d[m][i]);  
  31.         printf("%d\n",r);   
  32.               
  33.     }  
  34.   
  35.     //system("pause");  
  36.     return 0;  
  37. }  

3.3.6 HDU2546 饭卡

一开始直接背包DP,当饭卡余额大于5元时才跟新,最后最大值和卡上的钱的差就是余额..但是提交WA了

比如卡上8元,两种商品7元和2元,如果按照7,2的顺序跟新,2元的商品就不会去买了,因为买了7元的商品后余额就只有1元了..加上一个排序就过了,价值大的商品的后买,这样可以保证卡上最后余额最少.

  1. #include <cstdio>  
  2. #include <string.h>  
  3. #include <algorithm>   
  4. using namespace std;  
  5. int main(){  
  6.     int n,p[1005],m,d[1100];  
  7.     while(scanf("%d",&n),n){  
  8.         for(int i=1;i<=n;i++)scanf("%d",&p[i]);  
  9.         sort(p+1,p+1+n);  
  10.         scanf("%d",&m);  
  11.           
  12.         memset(d,0,sizeof d);  
  13.         d[0]=1;  
  14.         for(int i=1;i<=n;i++){  
  15.             //放宽50因为可能是负的   
  16.             for(int j=m+55;j>=p[i];j--){  
  17.                 //余额大于5元才可   
  18.                 if(j-p[i]<=m-5&&d[j-p[i]])d[j]=1;      
  19.             }  
  20.         }  
  21.         for(int i=m+55;i>=0;i--){  
  22.             if(d[i]==1){  
  23.                 printf("%d\n",m-i);  
  24.                 break;    
  25.             }     
  26.         }  
  27.     }  
  28.     return 0;     
  29. }  

3.3.7 HDU1203 I NEED A OFFER 

这题与3.3.4类似,背包的对象也是概率,是不能拿到Offer的概率最小p=(1-a1)(1-a2)...(1-an)


3.3.8 HDU3466 Proud Merchants

带有贪心性质的背包,按Q-P的值排序后再背包即可



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:45905次
    • 积分:1067
    • 等级:
    • 排名:千里之外
    • 原创:53篇
    • 转载:17篇
    • 译文:0篇
    • 评论:1条
    文章存档
    最新评论