hdu 1114Piggy-Bank(完全背包)
参考资料:
[1]:https://www.cnblogs.com/jbelial/articles/2116074.html
[2]:https://www.luogu.org/problemnew/solution/P1616
题意:
有一个小猪存钱罐,里面有各式各样的硬币,每种硬币有不同的面值和重量。
现测量出存钱罐初始的重量(E)和存满钱时的重量(F),问在这N种硬币中,如何选取,使得选取的硬币的总重量恰好等于(F-E),且总价值最小。
如果可以找到,输出"The minimum amount of money in the piggy-bank is num".(num : 总和最小的面值)
如果不能通过组合使得硬币总重量恰好等于(F-E),则输出"This is impossible."
分析:
乍一看,和“01”背包很想,所不同的是,在“01”背包中,第 i 种物品只有两种选择,拿或者不拿;
而此题,第 i 种面值的硬币可不止有拿与不拿这两种选择,而是有拿0,1,2,.....,k个,共(k+1)种选择,其中k满足 k*w[i] <= (F-E);
这种每种物品都有无限件可用的问题,称为“完全背包”问题。
题解:
1.完全背包转“01”背包
思路:将一种物品拆成多件物品。
考虑到第 i 种物品最多选 (F-E) / w[ i ] 件;
于是可以把第 i 种物品转化为 (F-E) / w[ i ] 件费用及价值均不变的物品,然后求解这个01背包问题。
如果开个二维的dp数组,指定不可行,具体为什么,请自行思考;
提示:假设每种硬币都可拆成 k 个(k 最大可达 10000),N种硬币则可拆成 N*k 个(N最大为500),所以最坏的情况是可拆成 N*k = 5e6 个物品。
比较好用的方法就是使用滚动数组优化空间。
更高效的转化方法是:把第 i 种物品拆成重量为 w[i]×2k、价值为 p[i]×2k 的若干件物品,其中k满足 w[i]×2k < (F-E)。
这是二进制的思想,因为不管最优策略选几件第 i 种物品,总可以表示成若干个 2k 件物品的和。
这样把每种硬币拆成 log2( (F-E) / w[i]) ) 件物品,是一个很大的改进。
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
const int maxn=+; int n;
int e,f;
int p[maxn],w[maxn];
int dp[]; void Solve()
{
int v=f-e;
for(int j=;j <= v;++j)
dp[j]=INF;
dp[]=; for(int i=;i <= n;++i)
{
for(int k=,cur=(<<k)*w[i];cur <= v;++k)///第i个物品选2^k个
{
for(int j=v;j >= cur;--j)
dp[j]=min(dp[j],dp[j-cur]+(<<k)*p[i]); cur <<= ;
}
}
if(dp[v] < INF)
printf("The minimum amount of money in the piggy-bank is %d.\n",dp[v]);
else
printf("This is impossible.\n");
}
int main()
{
int test;
scanf("%d",&test);
while(test--)
{
scanf("%d%d",&e,&f);
scanf("%d",&n);
for(int i=;i <= n;++i)
scanf("%d%d",p+i,w+i);
Solve();
}
return ;
}
2.我们有更优的O(VN)的算法
定义dp[ i ][ j ] : 前 i 件物品恰好组成重量 j 的最小面值;
第 i 件物品的状态转移方程为:
for(int j=w[i];j <= v;++j)
dp[j]=min(dp[j],dp[j-w[i]]+p[i]);
完全背包的特点恰是每种物品可选无限件,所以在考虑“加选一件第 i 种物品”这种策略时,
却正需要一个可能已选入第 i 种物品的子结果 dp[ i ][ v-w[i] ],所以就可以并且必须采用 j = w[i]..v 的顺序循环。
以上思路摘抄自[1]%%%%%%%%%%%%%%%
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
const int maxn=+; int n;
int e,f;
int p[maxn],w[maxn];
int dp[]; void Solve()
{
int v=f-e;
for(int j=;j <= v;++j)
dp[j]=INF;
dp[]=; for(int i=;i <= n;++i)
for(int j=w[i];j <= v;++j)
dp[j]=min(dp[j],dp[j-w[i]]+p[i]); if(dp[v] < INF)
printf("The minimum amount of money in the piggy-bank is %d.\n",dp[v]);
else
printf("This is impossible.\n");
}
int main()
{
int test;
scanf("%d",&test);
while(test--)
{
scanf("%d%d",&e,&f);
scanf("%d",&n);
for(int i=;i <= n;++i)
scanf("%d%d",p+i,w+i);
Solve();
}
return ;
}
hdu 1114Piggy-Bank(完全背包)的更多相关文章
- hdu 2546 典型01背包
分析:每种菜仅仅可以购买一次,但是低于5元不可消费,求剩余金额的最小值问题..其实也就是最接近5元(>=5)时, 购买还没有买过的蔡中最大值问题,当然还有一些临界情况 1.当余额充足时,可以随意 ...
- HDU 3127 WHUgirls(完全背包)
HDU 3127 WHUgirls(完全背包) http://acm.hdu.edu.cn/showproblem.php? pid=3127 题意: 如今有一块X*Y的矩形布条, 然后有n种规格的x ...
- HDU 3535 分组混合背包
http://acm.hdu.edu.cn/showproblem.php?pid=3535 题意:有n组工作,T时间,每个工作组中有m个工作,改组分类是s,s是0是组内至少要做一件,是1时最多做一件 ...
- HDU 4003 (树形DP+背包)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4003 题目大意:有K个机器人,走完树上的全部路径,每条路径有个消费.对于一个点,机器人可以出去再回来 ...
- HDU 1561 (树形DP+背包)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1561 题目大意:从树根开始取点.最多取m个点,问最大价值. 解题思路: cost=1的树形背包. 有 ...
- HDU 1011 (树形DP+背包)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1011 题目大意:树上取点,先取父亲,再取儿子.每个点,权为w,花费为cost,给定m消费总额,求最大 ...
- hdu 3535 AreYouBusy 分组背包
AreYouBusy Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Probl ...
- hdu 3339 In Action 背包+flyod
In Action Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=333 ...
- hdu 1963 Investment 多重背包
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1963 //多重背包 #include <cstdio> #include <cstr ...
- hdu 2955 Robberies 0-1背包/概率初始化
/*Robberies Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...
随机推荐
- bash处理一条命令的步骤
Shell执行一条命令步骤 参考链接: <Learning the bash Shell, 3rd Edition -- 7.3. Command-Line Processing> &l ...
- cf946d 怎样逃最多的课dp
来源:codeforces D. Timetable Ivan is a student at Berland ...
- 关于dreamweaver的软件测评
最近在用javascript编写程序,于是便用到了dreamweaver .所以,想写一个关于dreamweaver的软件测评. 学生本人使用的是dreamweaver 8.首先,谈谈本人使用感受,打 ...
- Android 學習之旅!(1)
就這樣就過去了一年加一個學期,現在是大二第二個學期而且是下半學期了,以前都是無所事事,沒事睡睡覺,打打遊戲就過去了,但是想到家境和以後的路,我還是決心自己找點東西學習下,以後出去還能有一技之長(雖然可 ...
- <构建之法>第11、12章
第11章软件设计与实现 主要讲了典型的开发流程和开发阶段的一些管理方法 问题: 从spec道实现是代码的实现吗? 第12章 用户体验 主要讲了用户体验的各种角度和认识阻力登 问题: 用户的体验是设计前 ...
- Java与JavaScript 完美实现字符串拆分(利用数组存储)与合并的互逆操作
Java: String typeStr = "1,2"; String[] typeArray = typeStr.split(","); typeStr = ...
- [转帖]从 2G 到 5G,手机上网话语权的三次改变
从 2G 到 5G,手机上网话语权的三次改变 美国第一大电信运营商 Verizon 公司的 CEO Hans Vestberg 手持一部 iPad,屏幕上显示俯瞰地面的飞行地图.400 多公里外的洛杉 ...
- [日常工作] SUSE设置上网ip地址
1. 同事搜到的命令 ifconfig eth0 10.24.25.8 netmask 255.255.0.0 up route add default gw 10.24.255.254 2. 修改 ...
- 转《发布ionic应用到App Store的完整步骤 》
当我们开发完一个应用,就到了发布到市场的时候,Android的打包比较简单,签名之后可以放在我们自己的服务器上,让用户扫描二维码来下载,而苹果的就比较麻烦了,如果内测可以通过蒲公英等内测分发平台,但是 ...
- zookeeper和kafka的安装
一.安装zookeeper yum install -y java ##安装jdk1.6版本以上 wget http://mirror.bit.edu.cn/apache/zookeeper/zook ...