传送门

参考资料:

  [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. bash处理一条命令的步骤

    Shell执行一条命令步骤 参考链接: <Learning the bash Shell, 3rd Edition  -- 7.3. Command-Line Processing> &l ...

  2. cf946d 怎样逃最多的课dp

    来源:codeforces                                              D. Timetable Ivan is a student at Berland ...

  3. 关于dreamweaver的软件测评

    最近在用javascript编写程序,于是便用到了dreamweaver .所以,想写一个关于dreamweaver的软件测评. 学生本人使用的是dreamweaver 8.首先,谈谈本人使用感受,打 ...

  4. Android 學習之旅!(1)

    就這樣就過去了一年加一個學期,現在是大二第二個學期而且是下半學期了,以前都是無所事事,沒事睡睡覺,打打遊戲就過去了,但是想到家境和以後的路,我還是決心自己找點東西學習下,以後出去還能有一技之長(雖然可 ...

  5. <构建之法>第11、12章

    第11章软件设计与实现 主要讲了典型的开发流程和开发阶段的一些管理方法 问题: 从spec道实现是代码的实现吗? 第12章 用户体验 主要讲了用户体验的各种角度和认识阻力登 问题: 用户的体验是设计前 ...

  6. Java与JavaScript 完美实现字符串拆分(利用数组存储)与合并的互逆操作

    Java: String typeStr = "1,2"; String[] typeArray = typeStr.split(","); typeStr = ...

  7. [转帖]从 2G 到 5G,手机上网话语权的三次改变

    从 2G 到 5G,手机上网话语权的三次改变 美国第一大电信运营商 Verizon 公司的 CEO Hans Vestberg 手持一部 iPad,屏幕上显示俯瞰地面的飞行地图.400 多公里外的洛杉 ...

  8. [日常工作] SUSE设置上网ip地址

    1. 同事搜到的命令 ifconfig eth0 10.24.25.8 netmask 255.255.0.0 up route add default gw 10.24.255.254 2. 修改 ...

  9. 转《发布ionic应用到App Store的完整步骤 》

    当我们开发完一个应用,就到了发布到市场的时候,Android的打包比较简单,签名之后可以放在我们自己的服务器上,让用户扫描二维码来下载,而苹果的就比较麻烦了,如果内测可以通过蒲公英等内测分发平台,但是 ...

  10. zookeeper和kafka的安装

    一.安装zookeeper yum install -y java ##安装jdk1.6版本以上 wget http://mirror.bit.edu.cn/apache/zookeeper/zook ...