HDU 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(多重背包,经典入门题)
来源:互联网 发布:行而知天下 编辑:程序博客网 时间:2024/06/05 10:49
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2191
题意:
C组测试数据
每组输入n,m,n:总经费 m:大米种类
输入每种大米的价格,重量,袋数(即库存)
问:最多能买多少大米(输出重量)
解题思路:
将多重背包转化为01背包,就是假设每一种米都只有一袋,那结果就只有两种:取或不取
很明显,直接可以用01背包解决
#include <cstdio>#include <cstring>#include <string>#include <iostream>#include <algorithm>using namespace std;struct node{int v,w;}p[2005];int ans[105];int main(){int t;scanf("%d",&t);while(t--){int n,m,pi,h,c,l=0;memset(p,0,sizeof(p));memset(ans,0,sizeof(ans));scanf("%d%d",&n,&m);for(int i=0;i<m;i++){scanf("%d%d%d",&pi,&h,&c);while(c--){p[l].v=pi;p[l].w=h;l++;}}for(int i=0;i<l;i++){for(int j=n;j>=p[i].v;j--){ans[j] = max(ans[j],ans[j-p[i].v]+p[i].w);}}printf("%d\n",ans[n]);}return 0;}
然而,当数据特别大时,用这种方法会超时
可以用二进制的那种多重背包
二进制的多重背包实际上也还是转化为01背包和完全背包,只不过用了二进制,大大缩短了时间
首先要弄明白一点:
对于一个数n来说,他可以被拆成 n = a1*2^0+a2*2^1+a3*2^2.....+ak*2^(k-1)+res
=a + b + c +d + .... + e + res
其中a1,a2,a3……的值是0,1,res是剩余的不能转化为2的k次方的数
这样表示的好处就是,可以用a b c d e res表示n以内的任意数
比如n=13,n = 1+2+4+6
1 = 1
2 = 2
3 = 1+2
4 = 4
5 = 1+4
6 = 2+4
7 = 1+6等等
多重背包总会涉及到一个数量的问题,同样的,我们可以将数量用2的k次方表示
回归本题
对每一种米都枚举过去
如果这种米的 数量x单价>n,就说明拥有经费n时,想买这种米与它的数量无关,可以用完全背包,因为即使花掉所有的经费,你也不能买下这种所有的米
否则就用01背包
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <string>using namespace std;#define N 105int n,m;struct Rice{ int price; int weight; int number;}rice[N];int dp[N]; void CompletePack(int cost,int weight)//完全背包{ for(int i=cost;i<=n;i++){ dp[i]=max(dp[i],dp[i-cost]+weight); }}void ZeroOnePack(int cost,int weight)//01背包{ for(int i=n;i-cost>=0;i--){ dp[i]=max(dp[i],dp[i-cost]+weight); }}void MultiplePack(int cost,int weight,int number)//多重背包{ //如果大于等于金额,就按完全背包处理(此时相当于不限定袋数) if(cost*number>=n){ CompletePack(cost,weight); return ; } int k=1; while(k<number){ ZeroOnePack(k*cost,k*weight);//注意要*k number-=k; k*=2; } ZeroOnePack(number*cost,number*weight);}int main(){ int _case; scanf("%d",&_case); while(_case--){ scanf("%d%d",&n,&m); memset(dp,0,sizeof(dp)); for(int i=0;i<m;i++){ scanf("%d%d%d",&rice[i].price,&rice[i].weight,&rice[i].number); } for(int i=0;i<m;i++){ MultiplePack(rice[i].price,rice[i].weight,rice[i].number); } printf("%d\n",dp[n]); } return 0;}
0 0
- HDU 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(多重背包,经典入门题)
- HDU-2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(多重背包 入门题)
- hdu 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 多重背包
- hdu 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(多重背包)
- HDU 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 多重背包
- hdu 2191悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 (多重背包)
- hdu 2191 (多重背包)悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
- HDU 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(多重背包)
- HDU 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活( 多重背包 )
- hdu 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 (多重背包)
- hdu 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 多重背包
- HDU 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 多重背包
- HDU 2191悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(多重背包)
- HDU 2191(悼念512汶川大地震遇难同胞——珍惜现在,感恩生活)多重背包
- hdu 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 多重背包
- HDU 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 多重背包
- HDU 2191 - 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(多重背包)
- HDU 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(多重背包)
- 使用MG-SOFT的MIB Builder编写mib文件或者.my文件方法
- 黑马程序员----JAVA基础----集合
- 基于Jpcap的Java ARP断网攻击
- 内联函数的讲解
- mybatis自动生成表的配置文件
- HDU 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(多重背包,经典入门题)
- 将图片文件流转换成base64字符串
- 2012年5月SAT香港真题解析
- GRE写作必备句型
- sublime text2 插件 zencoding的安装及使用
- 日志管理--log4j
- POJ 1008 Maya Calendar
- backtrace&&backtrace_symbols 查找段错误 打印堆栈信息
- Aladdin and the Flying Carpet