这是一道贪心的题目
首先要注意的是计算最多硬币数及逆向计算留下的钱的最少硬币数
还有要枚举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; }