杭電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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章