杭电2019多校第九场 HDU-6685 Rikka with Coin(思维+暴力)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=6685

题意:T组样例,每组样例会给出n个数,现在你有无穷多的10、20、50、100的硬币,问最少带多少硬币,可以这n个数都可以凑出来。如果不能输出-1。

思路:首先,如果不能整除10,肯定就是-1。比赛时,思路是分类讨论,零头也就是10、20、30、40、50、50+10、50+20、50+30、50+40,这9种情况。如果大于50,就像式子写的那样,用一个50,剩下的又变成了10、20、30、40。所以,最后零头也就有10、20、30、40、50,对这5种情况分类讨论。事实证明这种思路是错误的,比如20、40、60,只用3个20就行。如果按我的思路,要用1个10,2个20,1个50。然后,加了特判还是WA了。队友又给了一个样例150、190、210,这时,只要100/50/20/20/20。也就是说,存在不用50,而用之前有的凑。那这样,情况太多了,根本没法讨论。正如上面的样例,10最多有1个,20最多有3个(用3个20凑60,如果是80,用1个10,1个20,1个50显然更优,这样还能凑出10、20、30。),50最多有1个,100的个数要么是w[i]/100要么是w[i]/100-1,暴力检查即可。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n,w[110];
bool check(int i1,int i2,int i5,int x)
{
	for(int i=0;i<=i1;i++)
		for(int j=0;j<=i2;j++)
			for(int k=0;k<=i5;k++)
				if(i*10+j*20+k*50==x)
					return 1;
	return 0;
}
int main(void)
{
	int t,i10,ans;
	bool can,no;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		ans=1e9,no=0;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&w[i]);
			if(w[i]%10) no=1;
		}
		if(no)
		{
			printf("-1\n"); continue;	
		}	
		sort(w+1,w+1+n);
		n=unique(w+1,w+1+n)-(w+1);
		for(int i1=0;i1<=1;i1++)
			for(int i2=0;i2<=3;i2++)
				for(int i5=0;i5<=1;i5++)
				{
					i10=0,can=1;
					for(int i=1;i<=n;i++)
					{
						if(w[i]<100)
						{
							if(!check(i1,i2,i5,w[i]))	
								can=0;						
						}
						else if(check(i1,i2,i5,w[i]%100+100))
							i10=max(i10,w[i]/100-1);
						else if(check(i1,i2,i5,w[i]%100))
							i10=max(i10,w[i]/100);
						else
						{
							can=0;
							break;
						}
					}
					if(can) ans=min(ans,i1+i2+i5+i10);
				}
		printf("%d\n",ans);
	}
	
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值