hdu 2111 Saving HDU (01背包)
2013-10-29 17:07
302 查看
Saving HDU
[b]Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4917 Accepted Submission(s): 2240
[/b]
[align=left]Problem Description[/align]
话说上回讲到海东集团面临内外交困,公司的元老也只剩下XHD夫妇二人了。显然,作为多年拼搏的商人,XHD不会坐以待毙的。
一天,当他正在苦思冥想解困良策的时候,突然想到了自己的传家宝,那是公司成立的时候,父亲作为贺礼送来的一个锦囊,徐父当时交代,不到万不得已的时候,不要打开它。“现在不正是最需要的时候吗?”,一边想,XHD一边找到了这个精心保管的锦囊,打开一看,里面只有一句话“杭城北麓千人洞有宝”。
二话不说,XHD拿起一个大口袋就出发了,这个千人洞他是知道的,小的时候,爸爸曾经带他来过这个隐蔽的路口,并告诉他,这是千人洞。他现在才明白爸爸当初这句话的含义。
尽管有点印象,XHD还是花了很大的精力才找到这个异常隐蔽的洞口,走进一看,几乎惊呆了,真的是眼花缭乱!不过尽管宝贝的种类不少,但是每种宝贝的量并不多,当然,每种宝贝单位体积的价格也不一样,为了挽救HDU,现在请你帮忙尽快计算出来XHD最多能带回多少价值的宝贝?(假设宝贝可以分割,分割后的价值和对应的体积成正比)
[align=left]Input[/align]
输入包含多个测试实例,每个实例的第一行是两个整数v和n(v,n<100),分别表示口袋的容量和宝贝的种类,接着的n行每行包含2个整数pi和mi(0<pi,mi<10),分别表示某种宝贝的单价和对应的体积,v为0的时候结束输入。
[align=left]Output[/align]
对于每个测试实例,请输出XHD最多能取回多少价值的宝贝,每个实例的输出占一行。
[align=left]Sample Input[/align]
2 2 3 1 2 3 0
[align=left]Sample Output[/align]
5 经过锦囊相助,HDU会脱离危机吗? 欲知后事如何,且听下回分解——
这道题可以用01背包水过,数据很小。但如果数据很大的话就应该用多重背包做。
01背包算法:
#include<stdio.h> #include<string.h> #define N 105 int f ,v; int max(int a,int b) { return a>b?a:b; } int main() { int i,j,k,n; int w ,num ; while(scanf("%d",&v)&&v) { memset(f,0,sizeof(f)); scanf("%d",&n); for(i=0;i<n;i++) { scanf("%d%d",&w[i],&num[i]); for(j=v;j>0;j--) //f[i][v]=max(f[i-1][v],f[i-1][v-k]+w[i]*k) { for(k=1;k<=num[i]&&k<=j;k++) //限制条件 { f[j]=max(f[j],f[j-k]+w[i]*k); } } } printf("%d\n",f[v]); } return 0; }
多重背包算法:
#include<stdio.h> #include<string.h> #define N 105 int f ,v; int max(int a,int b) { return a>b?a:b; } void zero(int c,int w) { int i; for(i=v;i>=c;i--) f[i]=max(f[i],f[i-c]+w); } void comple(int c,int w) { int i; for(i=c;i<=v;i++) f[i]=max(f[i],f[i-c]+w); } void multi(int num,int w) //多重背包 { int k=1; if(num>=v) comple(1,w); //耗费一体积得到1w价值 else { while(k<num) { zero(k,k*w); //耗费一体积得到k*w价值 num-=k; k*=2; } zero(num,num*w); } } int main() { int i,n; int w ,num ; while(scanf("%d",&v)&&v) { memset(f,0,sizeof(f)); scanf("%d",&n); for(i=0;i<n;i++) { scanf("%d%d",&w[i],&num[i]); multi(num[i],w[i]); } printf("%d\n",f[v]); } return 0; }
相关文章推荐
- 第九周-求1000以内偶数和-2
- 用不用加油?
- 事务通用模板
- Js获取数组最大和最小值示例代码
- error: conflicting types for 'XXXX'
- C语言宽字符处理函数对照表
- Eclipse常用且不易记快捷键
- kefu
- java 接口小结
- maven
- rabbitmq常用命令
- 计算圆柱体表面积
- 多mysql实例下开发需要注意主从同步延迟
- 关于网页中行内元素的基线(baseline)、行高(line-height)、垂直对齐(vertical-align)等
- 红帽子linux6.4 安装oracle 10g
- Java学习-基本语法+基础知识
- (字符串的处理4.7.22)POJ 3337 Expression Evaluator(解析C风格的字符串)
- 吐槽一下Page Restore
- Ubuntu 13.10安装后你要做的8件事
- 解法三