题目描述
在 ACM 能够开展之前,必须准备预算,并获得必要的财力支持。该活动的主要收入来自于 Irreversibly Bound Money (IBM)。思路很简单。任何时候,某位 ACM 会员有少量的钱时,他将所有的硬币投入到小猪储钱罐中。这个过程不可逆,因为只有把小猪储钱罐打碎才能取出硬币。在足够长的时间之后,小猪储钱罐中有了足够的现金,用于支付 ACM 活动所需的花费。
但是,小猪储钱罐存在一个大的问题,即无法确定其中有多少钱。因此,我们可能在打碎小猪储钱罐之后,发现里面的钱不够。显然,我们希望避免这种不愉快的情况。唯一的可能是,称一下小猪储钱罐的重量,并尝试猜测里面的有多少硬币。假定我们能够精确判断小猪储钱罐的重量,并且我们也知道给定币种的所有硬币的重量。那么,我们可以保证小猪储钱罐中最少有多少钱。
你的任务是找出最差的情形,即判断小猪储钱罐中的硬币最少有多少钱。我们需要你的帮助。不能再贸然打碎小猪储钱罐了!
输入
输入包含 T 组测试数据。输入文件的第一行,给出了 T 的值。
对于每组测试数据,第一行包含 E 和 F 两个整数,它们表示空的小猪储钱罐的重量,以及装有硬币的小猪储钱罐的重量。两个重量的计量单位都是 g (克)。小猪储钱罐的重量不会超过 10 kg (千克),即 1 <= E <= F <= 10000 。每组测试数据的第二行,有一个整数 N (1 <= N <= 500),提供了给定币种的不同硬币有多少种。接下来的 N 行,每行指定一种硬币类型,每行包含两个整数 P 和 W (1 <= P <= 50000,1 <= W <=10000)。P 是硬币的金额 (货币计量单位);W 是它的重量,以 g (克) 为计量单位。
输出
对于每组测试数据,打印一行输出。每行必须包含句子 “The minimum amount of money in the piggy-bank is X.” 其中,X 表示对于给定总重量的硬币,所能得到的最少金额。如果无法恰好得到给定的重量,则打印一行 “This is impossible.” 。
示例输入
3
10 110
2
1 1
30 50
10 110
2
1 1
50 30
1 6
2
10 3
20 4
示例输出
The minimum amount of money in the piggy-bank is 60.
The minimum amount of money in the piggy-bank is 100.
This is impossible.
理解
当初我把这道题当成多重背包来理解了,后来演变成完全背包能不能转换成多重背包,因为就算这里有无穷个物品,但不可能超过容量,所以用容量除以每个物品的重量就是每件物品最多可以放的数量,但一直WA。后来翻翻答案发现这道题竟然是完全背包问题,目前我所理解的是,多重背包之所以叫多重背包,因为它是由01背包和完全背包组合而成的,当多重背包的物品数完全够用的时候就变成了完全背包问题。
期望
随着以后的学习,理解完全背包和多重背包的关系。
代码
#include<iostream> #include<cmath> using namespace std; #define MAXN 10100 int w[MAXN],v[MAXN]; int dp[MAXN]; int main(){ int T,E,F,W,N; cin>>T; while(T--){ cin>>E>>F; W=F-E; cin>>N; for(int i=0;i<N;i++) cin>>v[i]>>w[i]; for(int i=0;i<=W;i++) dp[i]=6e8;//给dp数组初始化一个比题目要求还大的数用来做较小比较 dp[0]=0;//这一步保证当dp[j]中j=w[i]时能正确判断 for(int i=0;i<N;i++){ for(int j=w[i];j<=W;j++) dp[j]=min(dp[j],dp[j-w[i]]+v[i]); } if(dp[W]!=6e8) cout<<"The minimum amount of money in the piggy-bank is "<<dp[W]<<'.'<<endl; else cout<<"This is impossible."<<endl; } return 0; }