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