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

转载 2013年12月04日 23:41:57

转自: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的值排序后再背包即可



HDU2602/HDU1114/HDU2191(重新整理一下01背包,完全背包,多重背包)

好长时间不做背包的问题,有一点遗忘,现在把这些问题整理一下~ 一.01背包(HDU2602) 题目:http://acm.hdu.edu.cn/showproblem.php?pid=2602 题意就...
  • riba2534
  • riba2534
  • 2017年01月11日 13:24
  • 826

简单的背包变形HDU1203,HDU2955

今天一直在写背包,不过中间停了一段时间在写shell。 一直在做01背包。今天做了这两题很相似的背包 首先是HDU1203 Speakless很早就想出国,现在他已经考完了所有需要的考试,准备了所有要...
  • u011044759
  • u011044759
  • 2014年03月08日 22:19
  • 624

HDU——2955Robberies(小数背包)

Robberies Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...
  • a88770202
  • a88770202
  • 2016年07月07日 13:11
  • 187

poj1014完全背包 hdu2191多重背包 经典二进制优化

多重背包或者完全背包转换成 01 背包问题就是多了个二进制优化 把它的件数C 用分解成若干个件数的集合 这里面数字可以组合成任意小于等于C 的件数,而且不会重复 之所以叫二进制分解,是因为这样分解可以...
  • Summer__show_
  • Summer__show_
  • 2016年05月25日 20:32
  • 621

背包——多重背包(hdu2191)

首先,如果对01背包不理解的同学请移步  http://blog.csdn.net/sm9sun/article/details/53235986 理解了01背包之后,我们来说明一下多重背包,多重背包...
  • sm9sun
  • sm9sun
  • 2016年11月20日 12:30
  • 173

【hdu2955】Robberies——01背包

题目: Robberies Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T...
  • CFhM_R
  • CFhM_R
  • 2016年03月08日 11:23
  • 317

HDU2546 饭卡(背包)

Problem Description 电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额。如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负)...
  • dlnumk
  • dlnumk
  • 2017年05月07日 18:46
  • 48

HDU2191(多重背包)

悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Jav...
  • the_love_story
  • the_love_story
  • 2016年08月02日 08:59
  • 123

HDU3466(背包先后顺序)

Proud Merchants   Problem Description Recently, iSea went to an ancient country. For such a long ...
  • the_love_story
  • the_love_story
  • 2016年08月11日 09:38
  • 547

HDU1114完全背包模板

Piggy-Bank Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tot...
  • NicoleYWJ
  • NicoleYWJ
  • 2017年08月09日 11:27
  • 71
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:HDU_Steps3.3 各种背包 HDU1114 HDU1171 HDU2191 HDU2955 HDU3496 HDU2546 HDU1203 HDU3466
举报原因:
原因补充:

(最多只允许输入30个字)