Euro Efficiency 1252 (正负完全背包 好题)

Euro Efficiency
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 3552 Accepted: 1522

Description

On January 1st 2002, The Netherlands, and several other European countries abandoned their national currency in favour of the Euro. This changed the ease of paying, and not just internationally.
A student buying a 68 guilder book before January 1st could pay for the book with one 50 guilder banknote and two 10 guilder banknotes, receiving two guilders in change. In short:50+10+10-1-1=68. Other ways of paying were: 50+25-5-1-1, or 100-25-5-1-1.Either way, there are always 5 units (banknotes or coins) involved in the payment process, and it
could not be done with less than 5 units.
Buying a 68 Euro book is easier these days: 50+20-2 = 68, so only 3 units are involved.This is no coincidence; in many other cases paying with euros is more efficient than paying with guilders. On average the Euro is more efficient. This has nothing to do, of course, with the value of the Euro, but with the units chosen. The units for guilders used to be: 1, 2.5, 5, 10, 25, 50,whereas the units for the Euro are: 1, 2, 5, 10, 20, 50.
For this problem we restrict ourselves to amounts up to 100 cents. The Euro has coins with values 1, 2, 5, 10, 20, 50 eurocents. In paying an arbitrary amount in the range [1, 100] eurocents, on average 2.96 coins are involved, either as payment or as change. The Euro series is not optimal in this sense. With coins 1, 24, 34, 39, 46, 50 an amount of 68 cents can be paid using two coins.The average number of coins involved in paying an amount in the range [1, 100] is 2.52.
Calculations with the latter series are more complex, however. That is, mental calculations.These calculations could easily be programmed in any mobile phone, which nearly everybody carries around nowadays. Preparing for the future, a committee of the European Central Bank is studying the efficiency of series of coins, to find the most efficient series for amounts up to 100 eurocents. They need your help.
Write a program that, given a series of coins, calculates the average and maximum number of coins needed to pay any amount up to and including 100 cents. You may assume that both parties involved have sufficient numbers of any coin at their disposal.

Input

The first line of the input contains the number of test cases. Each test case is described by 6 different positive integers on a single line: the values of the coins, in ascending order. The first number is always 1. The last number is less than 100.

Output

For each test case the output is a single line containing first the average and then the maximum number of coins involved in paying an amount in the range [1, 100]. These values are separated by a space. As in the example, the average should always contain two digits behind the decimal point. The maximum is always an integer.

Sample Input

3
1 2 5 10 20 50
1 24 34 39 46 50
1 2 3 7 19 72

Sample Output

2.96 5
2.52 3
2.80 4
 
//题意:
//给你六张钞票的面值,让你用这六张钞票,每张都有若干张,通过支付和找零,来表示1~~100之间的任意数,因为表示每个数有很多种方法
//但这块要求都要用最少的钞票数,最终把1~~100全部表示完后,将他们的最小钞票数相加再除以100,这是计算表示每一个数所用的最少钞票
//的平均数,还要计算表示这些数(1~~100)所用的最多的钞票数,因为,虽然求的都是最少钞票数,但表示没个数的最少钞票数
//是不相同的,这块让找的就是这些数(1~~100)中最少钞票的最大值。(比较绕口,我能解释的也就这么多了,希望有缘人能够理解)
AC代码
 
#include<stdio.h>
#include<string.h>
#include<math.h>
#define MIN(a,b) (a>b?b:a)
#define MAX(a,b) (a>b?a:b)
#define INF 0x3f3f3f
int a[6];
int sum[51001];
int main(){
	int t,n,m,i,j,k;
	scanf("%d",&t);
	while(t--)
	{
		memset(sum,INF,sizeof(sum));
		sum[0]=0;
		for(i=0;i<6;i++)
		{
			scanf("%d",&a[i]);
			n=MAX(n,a[i]);
		}
		for(i=0;i<6;i++)
		{
			for(j=a[i];j<=1500;j++)//这块开到1500就行了,因为用1表示100,也就100张
								   //但其中有找零的过程,最多也就1500张 
			{
				sum[j]=MIN(sum[j],sum[j-a[i]]+1);
			}
		}
		for(i=0;i<6;i++)
		{
			for(j=1500-a[i];j>=0;j--)
			{
				sum[j]=MIN(sum[j],sum[j+a[i]]+1);
			}
		}
		int max=-1;
		int s=0;
		for(i=0;i<=100;i++)
		{
			s+=sum[i];
			max=MAX(max,sum[i]);
		}
		printf("%.2f %d\n",s/100.0,max);//poj上要用%f提交,用%lf提交就错 
	}
	return 0;
}
 
 
//只用一次完全背包,将负的转化为正的(加100就行),具体看代码
 
<pre class="cpp" name="code">#include<stdio.h>
#include<string.h>
#include<math.h>
#define min(a,b) (a>b?b:a)
#define MAX(a,b) (a>b?a:b)
#define INF 0x3f3f3f3f
int sum[100010];
int a[12];
int main(){
	int t,n,m,i,j,k;
	while(scanf("%d",&t)!=EOF)
	{
		while(t--)  
		{
			k=100;
			memset(sum,INF,sizeof(sum));
			memset(a,0,sizeof(a));
			sum[100]=0;
			for(i=0;i<6;i++)
			{
				scanf("%d",&a[i]);
				a[i+6]=-a[i];
			}
			double s=0;
			int max=-1;
			while(k--)  //可能有多次找零和支付,对其循环100次就足够了			
			{
				for(i=0;i<12;i++)
				{
					for(j=a[i]+100;j<=1500;j++)
					{
						sum[j]=min(sum[j],sum[j-a[i]]+1);
					}
				}
			}
			for(i=1;i<=100;i++)
			{
				s+=sum[i+100];
				max=MAX(max,sum[i+100]);
			}				
			printf("%.2f %d\n",s/100,max);
		}
	}
	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值