阿美筹办ACM竞赛(完全背包问题,求最小值)

问题描述

 

Description

        若想顺利举办 一场ACM赛事,必须事先做好预算,并获得必要的财力支持。阿美接受任务后,甚是苦恼。于是找阿亮商量如何筹钱。思考了片刻,阿亮给出了馊主意:我们可以学习道观筹集香火钱的策略。我们制作一个超级迷人的存钱罐,摆放在学校的核心位置。这样,在任何时候,只要行者愿意,他就可以将随身携带的硬币投入到存钱罐中。这个过程不可逆,因为只有把存钱罐打碎才能取出硬币。相信在足够长的时间之后,存钱罐中肯定有足够的现金,用于支付 ACM 活动所需的花费。
        机灵的阿美反问道:存钱罐筹集ACM经费存在一个大问题呀,即无法随时确定其中有多少钱。因此,我们有可能在打碎存钱罐之后,发现里面的钱不够。
        阿亮说:我们可以通过称重来避免这种不愉快的情况。也就是说:称一下存钱罐的重量,并尝试猜测里面有多少硬币。假定我们能够精确判断存钱罐的重量,并且我们也知道给定币种的所有硬币的重量。那么,我们可以保证存钱罐中最少有多少钱。阿美拽着阿亮的衣角撒娇说:亮哥,这个识别任务就交给您了,您真是我的么么哒。

Input

输入包含 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 (克) 为计量单位。
 

Output

对于每组测试数据,打印一行输出。每行必须包含句子 “The minimum amount of money in the piggy-bank is X.” 其中,X 表示对于给定总重量的硬币,所能得到的最少金额。如果无法恰好得到给定的重量,则打印一行 “This is impossible.” 。

Sample Input

3
10 110
2
1 1
30 50
10 110
2
1 1
50 30
1 6
2
10 3
20 4

Sample Output

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.

 解题思路

https://blog.csdn.net/qq_39445165/article/details/84334970

完全背包问题,不过求的是最小值。

关键的一个步骤:dp[j]=min(dp[j],dp[j-wi[i]]+pi[i]);

刚开始一直不理解dp[j-wi[i]]这个表达的是什么,后来经过调试,理解了。通过dp[j]和dp[j-wi[i]]+pi[i]比较,取最小值存入,当前dp[j],已经被初始化为了10000000,dp[j-wi[i]]这个计算出的数,若是当前币种重量的倍数,则已经存入值,就不是10000000了,dp[j-wi[i]]+pi[i]计算出的数就会比10000000小,然后存入当前的dp[j],否则,dp[j]还是10000000。

代码

#include<stdio.h>
#include<algorithm>
using namespace std;
int dp[10005];

int main()
{
	int i,j,t,e,f,weight,n,pi[505],wi[505];
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&e,&f);
		weight=f-e;               //硬币的重量 
		for(i=1;i<=weight;i++)
		{
			dp[i]=10000000;     //初始化为最大值 
		}
		dp[0]=0;
		scanf("%d",&n);
		for(i=0;i<n;i++)
		{
			scanf("%d%d",&pi[i],&wi[i]);
		}
		for(i=0;i<n;i++)                      //遍历所有的币种 
		{
			for(j=wi[i];j<=weight;j++)
			{
				dp[j]=min(dp[j],dp[j-wi[i]]+pi[i]);  //关键步骤,每次存入最小值 
			}
		}
		if(dp[weight]==10000000)                  
		{
			printf("This is impossible.\n");
		}
		else
		{
			printf("The minimum amount of money in the piggy-bank is %d.\n",dp[weight]);
		}
	}
	return 0;
} 

 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值