HDU 5527

这是一道贪心的题目

首先要注意的是计算最多硬币数及逆向计算留下的钱的最少硬币数

还有要枚举50和500这两个例外的奇偶性

调试时要注意

  1 既然已经枚举了,取的时候一定要取偶数个

  2 计算总数量的时候一定要加上自己已经取得数目

  3 int 和long long不影响本题的结果

  4 枚举的时候一定要判断能否取出一枚50或500的硬币

  5 可能有一些枚举情况无解,这时要返回inf

  6 即使在取出钱数小于等于总钱数的情况下,也会有无解,这时一定要判断

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int inf=999999999;
inline int read(){
	int x=0,f=1,ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline int min(int x,int y){
	return x<y?x:y;
}
int a[10];
int id[10]={1,5,10,20,50,100,200,500,1000,2000};
int flag;
inline int cal(int x){
	int res=0;
	for(int i=9;i>=0;i--){
		int num=min(a[i],x/id[i]);
		x-=num*id[i];
		if(i==4||i==7) num<<=1;
		res+=num;
	}
	if(x) return inf;
	return res;
}
int main(){
	int T=read();
	while(T--){
		int p=read(),sum=0,cnt=0;
		for(int i=0;i<10;i++) a[i]=read(),sum+=a[i]*id[i],cnt+=a[i];
		if(p>sum){
			puts("-1");
			continue;
		}
		if(p==sum){
			printf("%d\n",cnt);
			continue;
		}
		// cout<<id[4]<<"\t"<<id[7]<<endl;
		p=sum-p;id[4]=100;id[7]=1000;
		// cout<<p<<endl;
		int ans,num1,num2;
		num1=a[4];num2=a[7];a[4]>>=1;a[7]>>=1;
		ans=cal(p);
		a[4]=num1;a[7]=num2;
		if(p>=50&&a[4]){
			p-=50;a[4]--;
			num1=a[4];num2=a[7];a[4]>>=1;a[7]>>=1;
			ans=min(ans,cal(p)+1);
			a[4]=num1;a[7]=num2;
			p+=50;a[4]++;
		}
		if(p>=500&&a[7]){
			p-=500;a[7]--;
			num1=a[4];num2=a[7];a[4]>>=1;a[7]>>=1;
			ans=min(ans,cal(p)+1);
			a[4]=num1;a[7]=num2;
			p+=500;a[7]++;
		}
		if(p>=550&&a[4]&&a[7]){
			p-=550;a[4]--;a[7]--;
			a[4]>>=1;a[7]>>=1;
			ans=min(ans,cal(p)+2);
		}
		id[4]=50;id[7]=500;
		if(ans==inf) puts("-1");
		else printf("%d\n",cnt-ans);
	}
	return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/gcyyzf/p/9695737.html
hdu