传送门

参考资料:

  [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(完全背包)的更多相关文章

  1. hdu 2546 典型01背包

    分析:每种菜仅仅可以购买一次,但是低于5元不可消费,求剩余金额的最小值问题..其实也就是最接近5元(>=5)时, 购买还没有买过的蔡中最大值问题,当然还有一些临界情况 1.当余额充足时,可以随意 ...

  2. HDU 3127 WHUgirls(完全背包)

    HDU 3127 WHUgirls(完全背包) http://acm.hdu.edu.cn/showproblem.php? pid=3127 题意: 如今有一块X*Y的矩形布条, 然后有n种规格的x ...

  3. HDU 3535 分组混合背包

    http://acm.hdu.edu.cn/showproblem.php?pid=3535 题意:有n组工作,T时间,每个工作组中有m个工作,改组分类是s,s是0是组内至少要做一件,是1时最多做一件 ...

  4. HDU 4003 (树形DP+背包)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4003 题目大意:有K个机器人,走完树上的全部路径,每条路径有个消费.对于一个点,机器人可以出去再回来 ...

  5. HDU 1561 (树形DP+背包)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1561 题目大意:从树根开始取点.最多取m个点,问最大价值. 解题思路: cost=1的树形背包. 有 ...

  6. HDU 1011 (树形DP+背包)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1011 题目大意:树上取点,先取父亲,再取儿子.每个点,权为w,花费为cost,给定m消费总额,求最大 ...

  7. hdu 3535 AreYouBusy 分组背包

    AreYouBusy Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Probl ...

  8. hdu 3339 In Action 背包+flyod

    In Action Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=333 ...

  9. hdu 1963 Investment 多重背包

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1963 //多重背包 #include <cstdio> #include <cstr ...

  10. hdu 2955 Robberies 0-1背包/概率初始化

    /*Robberies Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...

随机推荐

  1. linux-文件流4种读取方式

    第二种方式 第三种 第四种: 小括号在管道符的右边开辟了两个子进程 大括号在管道符的右边开辟了一个子进程, export 用来导出子进程的 num 还可以借助外部文件进行 七步扩展:

  2. 如何在java项目中使用lucene

    lucene是一个开源的全文检索引擎工具包,但它不是一个成型的搜索引擎,它的功能就是负责将文本数据按照某种分词算法进行分词,分词后的结果存储在索引库中,然后根据关键字从索引库检检索. 那么应该如何使用 ...

  3. 《Linux内核设计与实现》第三章读书笔记

    一.进程(任务)描述 1.进程是处于执行期的程序:除了可执行程序代码,还包括打开的文件.挂起的信号.内核内部数据.一个或者多个执行线程等多种资源 线程是在进程活动中的对象:内核调度的对象是线程而不是进 ...

  4. 实现基于SSH的门票管理系统开发的质量属性

    我要做的是一个基于SSH的门票售卖系统,在系统中常见的质量属性有:可用性.可修改性.性能.安全性.易用性. 可用性方面: 可用性是指系统正常运行时间的比例,是通过两次故障之间的时间长度或在系统崩溃情况 ...

  5. mybatis中批量更新的问题

    问题:使用mybatis在执批量更新操作时,一直报错执行失败 解决方法: 首先打印了SQL语句,发现SQL语句拿出来执行没问题,也可以批量执行.SQL没问题,应该是配置的问题. 在网上查询和很多资料, ...

  6. Appium学习笔记4_元素定位方法

    Appium之元素定位,如果对Android上如何使用工具获取页面元素有问题的,请转战到这:http://www.cnblogs.com/taoSir/p/4816382.html. 下面主要是针对自 ...

  7. 关于安装 rst2pdf 时遇到的 setuptools过老的问题

    由于想把flask里面的.rst文档 转一些成pdf方便查看和翻阅(.rst文档都非常新一直在维护) 所以查到一个模块rst2pdf 安装好之后却发现警告里面提示我的setuptools版本过老无法运 ...

  8. 02 基于umi搭建React快速开发框架(国际化)

    前言 之前写过一篇关于React的国际化文章,主要是用react-intl库,雅虎开源的.react-intl是用高阶组件包装一层来做国际化. 基于组件化会有一些问题,比如在一些工具方法中需要国际化, ...

  9. PKUWC 2019&WC 2019爆零记

    PKUWC 2019&WC 2019爆零记 毕竟过了很久了,杂七杂八的东西就不写了,并且除成绩之外的内容不保证其正确性. Day1 T1:看到这道题很舒服啊,枚举top序算合法图的数量,状压D ...

  10. 英国电信反悔华为是唯一真正的5G供应商

    导读 英国电信反悔华为是唯一真正的5G供应商 英国电信的一位发言人表示,该公司目前正「从我们自 2006 年以来实施的网络架构原则中,从我们的 3G 和 4G 网络核心提取华为设备」. 英国电信已经不 ...