HDU3348--coins(贪心+思维)

8 篇文章 0 订阅
6 篇文章 0 订阅

题意: 你有面值为1,5,10,50,100的钱币分别若干张;求购买某一价值的物品所花的最少和最多钱币数。

思路:
(1)最少的钱币数: 由于面值分别为1,5,10,50,100;大面值都可以由小面值凑数转化而来,故贪心策略适用,从大面值开始枚举,每次取当前能取的最大面值。
(2)最多的钱币数: 此时采用贪心策略不再成立了,因为若从小面值开始枚举,当前的最优解并不一定是全局的最优解了。(i.e. 商品价值为6,你有2张1,1张5,此时若按贪心策略,你先把1取完,还要凑4,但是你已经没有1,只剩下一张5了;但其实明明可以取1张1,1张5达到目标的),这是因为当前最优状态不能转移下去了,故可以采用DP做,也可以采用逆向思维继续用贪心,我要用出去最多,即我要剩下的最小,即对于总价值为(sum-price),求最小的钱币数,这就转化为(1)的问题了,最后总数减掉求出的剩下的最小钱币数就是用出的最大钱币数。

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int main()
{
	int i,j;
	int n,m;
	int t;
	ll a[10];//a[i]为每个价格对应的钱币的数量; 
	ll value[]={0,1,5,10,50,100};//value[i]对应各个价格; 
	ll price,sum;//price为商品的价值,sum为你有的总钱数; 
	scanf("%d",&t);
	while(t--)
	{
		scanf("%lld",&price);
		sum=0;
		for(i=1;i<=5;i++)
		{
			scanf("%lld",&a[i]);
			sum+=a[i]*value[i];
		}
		
		if(sum<price) 
		{
			printf("-1 -1\n");
			continue;
		}
		
		ll ans1,ans2;
		ans1=ans2=0;
		ll now;
		
		//求使用最少钱币数时,贪心从大面值往小枚举; 
		now=price;
		for(i=5;i>=1;i--)
		{
			if(now==0) break;
			if(now>=value[i] && a[i]!=0)
			{
				ll num=(now/value[i]);
				if(num>a[i])//数量不够
				{
					now-=a[i]*value[i];
					ans1+=a[i];
				}
				else
				{
					now-=num*value[i];
					ans1+=num;
				}
			}
		}  
		
		if(now!=0)
		{
			printf("-1 -1\n");
			continue;
		} 
		 
		//求使用最多钱币数时,逆向转化为自己剩最少的钱币数才能继续使用贪心策略;
		//这样转化的话,问题变为对总价值为sum-price的价值求最少钱币数; 
		now=sum-price;
		for(i=5;i>=1;i--)
		{
			if(now==0) break;
			if(now>=value[i] && a[i]!=0)
			{
				ll num=(now/value[i]);
				if(num>a[i])//数量不够
				{
					now-=a[i]*value[i];
					ans2+=a[i];
				}
				else
				{
					now-=num*value[i];
					ans2+=num;
				}
			}
		}  
		
		
		if(now!=0)
		{
			printf("-1 -1\n");
			continue;
		} 
		
		//钱币总数减去自己保留的最少的钱币数就是最多的钱币数; 
		ans2=(a[1]+a[2]+a[3]+a[4]+a[5])-ans2; 
		printf("%lld %lld\n",ans1,ans2); 
	}
	return 0;
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值