【日常学习】【背包DP(完全背包)】洛谷1616 疯狂的采药题解
2015-08-09 10:22
323 查看
这是一道典型的完全背包题目
先上题目···于是又要迎来洛谷那令人不知道说什么的霸气摘要···
本题地址: http://www.luogu.org/problem/show?pid=1616
此题为NOIP2005普及组第三题的疯狂版。 此题为纪念LiYuxiang而生。
LiYuxiang是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同种类的草药,采每一种都需要一些时间,每一种也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”
如果你是LiYuxiang,你能完成这个任务吗?
此题和原题的不同点:
1.每种采药可以无限制地疯狂采摘。
2.药的种类眼花缭乱,采药时间好长好长啊!师傅等得菊花都谢了!
输入格式:
输入第一行有两个整数T(1 <= T <= 100000)和M(1 <= M <= 10000),用一个空格隔开,T代表总共能够用来采药的时间,M代表山洞里的草药的数目。接下来的M行每行包括两个在1到10000之间(包括1和10000)的整数,分别表示采摘某种草药的时间和这种草药的价值。
输出格式:
输出一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。
输入样例#1:
输出样例#1:
对于30%的数据,M <= 1000;
对于全部的数据,M <= 10000。
完全背包问题(物体可以选无限件)解决方案:
再看01背包如何解决:
我们惊奇地发现,两者的区别仅仅在于枚举体积循环,01背包是倒序,完全背包是正序。这是因为01背包要保证求解f[j]时,f[j-c[i]]是f[i-1][j-c[i]]而不是f[i][j-c[i]]。而完全背包恰恰相反,因为物品可选无数件,我们“选这件”需要考虑这件可能已经选了一些的情况,因此要保证求解f[j]时,f[j-c[i]]指的是f[i][j-c[i]]。
对于完全背包问题的常数优化,可以用“一种简单有效的优化”,就是把价值低于某物品且体积高于某物品的物品删去。背包九讲中提到可以用O(n²)或者O(V+N)的方案实现,但我并不明白具体如何实现,是将该物品对应的两个数组元素赋值为0或某个值,还是怎么样?
无论如何,先把代码放上来吧
——浮天水送无穷树,带雨云埋一半山
先上题目···于是又要迎来洛谷那令人不知道说什么的霸气摘要···
洛谷1616 疯狂的采药
本题地址: http://www.luogu.org/problem/show?pid=1616
题目背景
此题为NOIP2005普及组第三题的疯狂版。 此题为纪念LiYuxiang而生。
题目描述
LiYuxiang是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同种类的草药,采每一种都需要一些时间,每一种也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。” 如果你是LiYuxiang,你能完成这个任务吗?
此题和原题的不同点:
1.每种采药可以无限制地疯狂采摘。
2.药的种类眼花缭乱,采药时间好长好长啊!师傅等得菊花都谢了!
输入输出格式
输入格式:输入第一行有两个整数T(1 <= T <= 100000)和M(1 <= M <= 10000),用一个空格隔开,T代表总共能够用来采药的时间,M代表山洞里的草药的数目。接下来的M行每行包括两个在1到10000之间(包括1和10000)的整数,分别表示采摘某种草药的时间和这种草药的价值。
输出格式:
输出一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。
输入输出样例
输入样例#1:70 3 71 100 69 1 1 2
输出样例#1:
140
说明
对于30%的数据,M <= 1000;对于全部的数据,M <= 10000。
完全背包问题(物体可以选无限件)解决方案:
for (int i=1;i<=m;i++) { for (int j=v[i];j<=t;j++) { f[j]=max(f[j],f[j-v[i]]+c[i]); } }
再看01背包如何解决:
for (int i=1;i<=n;i++) { for (int j=v;j>=a[i];j--) { f[j]=max(f[j],f[j-a[i]]+a[i]); } }
我们惊奇地发现,两者的区别仅仅在于枚举体积循环,01背包是倒序,完全背包是正序。这是因为01背包要保证求解f[j]时,f[j-c[i]]是f[i-1][j-c[i]]而不是f[i][j-c[i]]。而完全背包恰恰相反,因为物品可选无数件,我们“选这件”需要考虑这件可能已经选了一些的情况,因此要保证求解f[j]时,f[j-c[i]]指的是f[i][j-c[i]]。
对于完全背包问题的常数优化,可以用“一种简单有效的优化”,就是把价值低于某物品且体积高于某物品的物品删去。背包九讲中提到可以用O(n²)或者O(V+N)的方案实现,但我并不明白具体如何实现,是将该物品对应的两个数组元素赋值为0或某个值,还是怎么样?
无论如何,先把代码放上来吧
——浮天水送无穷树,带雨云埋一半山
相关文章推荐
- linux自定义脚本添加到rc.local脚本无法正常运行的问题
- china-pub
- 生活记录(1)
- 内存泄露
- POJ 3050 Hopscotch (穷竭搜索)
- VM克隆虚拟机不能上网的一些小问题。
- POJ - 3667 Hotel (线段树 + 区间合并)
- 学点平面知识丨快速去除水印
- java i/o操作
- HDU 2759 Billboard 线段树
- Hadop使用Partitioner后,结果还是一个文件,如何解决??
- jQuery操作Select
- 精挑细选
- BestCoder Round #50 (div.2)
- NYOJ 823 人形序列
- oc基础第四天-继承
- Cocos2d-x 2.0 TestCpp框架源码分析
- m进制转10进制
- 设计模式学习之---模板方法设计模式
- 输出所有“水仙花数”