C - Piggy-Bank HDU - 1114

在acm能够做任何事情之前, 必须编制预算并获得必要的财政支持。这一行动的主要收入来自IBM。这个想法其实很简单,每当一些会员有一点小钱时,他就会把所有的硬币都扔到小猪存钱罐里。这个过程是不可逆转的, 除非打破猪,否则硬币不能拿出来。过了足够长的时间, 存钱罐里应该有足够的现金来支付所有需要支付的费用。

但存钱罐存在很大问题:不可能确定里面有多少钱。所以我们可能敲破猪才发现没有足够的钱。显然, 我们要避免这种不愉快的情况,唯一的可能是称重猪,并试图猜测里面有多少枚硬币。假设我们能够准确地确定猪的重量, 而且我们知道给定货币的所有硬币的重量。然后在存钱罐里有一些最低数量的钱, 我们可以保证。你的任务是找出这个最坏的情况, 并确定在存钱罐内的最低现金金额。

Input

输入由 T组测试用例组成。它们的数量T是在输入文件的第一行给出的。每个测试用例以包含两个整E和 F 的行开头(E和F以克为单位),它们表明了空猪和装满硬币的猪的重量。两个权重都以克为值。任何猪的重量都不会超过10公斤, 这意味着 1 < = E < = F < = 10000。在每个测试用例的第二行, 有一个整数数字 N (1 < = N < = 500), 给出给定货币中使用的各种硬币的数量。下面是 N 行, 每行都指定一种硬币类型。这些行包含两个整数, P, W (1 < = P < = 50000, 1 < = W < = 10000)。P 是硬币的价值, W是它的重量(以克为单位)。

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.

 

#include <iostream>
#include <algorithm>
#include <stdlib.h>
#include <math.h>
#include <string.h>

using namespace std;

int value[5005];
int height[5005];
int dp[20005];

int main()
{
	int T;
	while(scanf("%d",&T)!=EOF)
	{
		while(T--)
		{
			int e,f;
			memset(dp,0x3f,sizeof(dp));
			dp[0] = 0;
			scanf("%d %d",&e,&f);
			int q = f-e;
			int n;
			scanf("%d",&n);
			for(int i=1;i<=n;i++)
			{
				scanf("%d %d",&value[i],&height[i]);
			}
			for(int i=1;i<=n;i++)
			{
				for(int j=height[i];j<=q;j++)
				{
					dp[j] = min(dp[j],dp[j-height[i]] + value[i]);
				}
			}
			if(dp[q] == 0x3f3f3f3f)
				printf("This is impossible.\n");
			else
				printf("The minimum amount of money in the piggy-bank is %d.\n",dp[q]);
		
		}
	}

	return 0;
}

完全背包,主要学会了0x3f3f3f3f为无穷大,0x800000为无穷小

优点:

  1. 0x3f3f3f3f的十进制是1061109567,也就是10^9级别的(和0x7fffffff一个数量级),而一般场合下的数据都是小于10^9的,所以它可以作为无穷大使用而不致出现数据大于无穷大的情形。
  2. 另一方面,由于一般的数据都不会大于10^9,所以当我们把无穷大加上一个数据时,它并不会溢出(这就满足了“无穷大加一个有穷的数依然是无穷大”),事实上0x3f3f3f3f+0x3f3f3f3f=2122219134,这非常大但却没有超过32-bit int的表示范围,所以0x3f3f3f3f还满足了我们“无穷大加无穷大还是无穷大”的需求。
  3. 最后,0x3f3f3f3f还能给我们带来一个意想不到的额外好处:如果我们想要将某个数组清零,我们通常会使用memset(a,0,sizeof(a))这样的代码来实现(方便而高效),但是当我们想将某个数组全部赋值为无穷大时(例如解决图论问题时邻接矩阵的初始化),就不能使用memset函数而得自己写循环了(写这些不重要的代码真的很痛苦),我们知道这是因为memset是按字节操作的,它能够对数组清零是因为0的每个字节都是0,现在好了,如果我们将无穷大设为0x3f3f3f3f,那么奇迹就发生了,0x3f3f3f3f的每个字节都是0x3f!所以要把一段内存全部置为无穷大,我们只需要memset(a,0x3f,sizeof(a))。

所以在通常的场合下,0x3f3f3f3f真的是一个非常棒的选择。

无论哪种int类型都有其表达范围,其中
16位int能表示的范围为-32768~+32767
32位int能表示的范围为-2147483648~+2147483647

从这个可以看出,int是无法表达真正的无穷大和无穷小的。
一般有如下两种情况:
1 程序中对处理的数据规模有限制,比如程序中输入的数值只在0~100之间,那么可以设定无穷大为101,而无穷小为-1。因为它们也是在使用中无法达到的值。
2 程序中对数据规模没有明确的规定。但是既然应用的int类型,就必须是int类型可以容纳的,否则出现溢出就可能导致错误。 这样,可以用int所能表示的最大值和最小值用做无穷大和无穷小。
比如在32位情况下,无穷小可以是-2147483648,无穷大是2147483647。
如此长的一段数据是很难记忆的,由计算机对整型数据的存储原理可以得知,这两个数值的二进制值分别为0x80000000和0x7FFFFFFF。
类似的在16位下,无穷大为0x7FFF,无穷小为0x8000。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值