题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1114
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 34490 Accepted Submission(s): 17088
汉化版:
在ACM能够开展之前,必须准备预算,并获得必要的财力支持。该活动的主要收入来自于不可逆的捆绑金钱(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(克)为计量单位。
输出
对于每组测试数据,打印一行输出。每行必须包含句子“存钱罐中的最小金额是X.”其中,X表示对于给定总重量的硬币,所能得到的最少金额。如果无法恰好得到给定的重量,则打印一行“这是不可能的。”
示例输入
3
10 110
2
1 1
30 50
10 110
2
1 1
50 30
1 6
2
10 3
20 4
示例输出
存钱罐中
的最低金额是60.存钱罐中的最低金额是100.
这是不可能的。
思路:完全背包,动态规划的应用!
//dp[i] : 表示存钱罐空间为 i 的最小价值;
空间为0时的价值为0,其他都初始化为正无穷!
#include<string.h>
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=0x3f3f3f3f;
int main()
{
int dp[10002],a[10002],b[10001];
int t;
scanf("%d",&t);
while(t--)
{
memset(dp,maxn,sizeof(dp)); //初始化
dp[0]=0;
int m,m1;
scanf("%d %d",&m,&m1);
m1=m1-m;
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d %d",&a[i],&b[i]);
for(int i=0;i<n;i++) //完全背包
{
for(int j=b[i];j<=m1;j++)
{
dp[j]=min(dp[j],dp[j-b[i]]+a[i]);
}
}
if(dp[m1]!=maxn)
printf("The minimum amount of money in the piggy-bank is %d.\n",dp[m1]);
else
printf("This is impossible.\n");
}
return 0;
}