一个比较好的贪心题 : http://acm.hdu.edu.cn/showproblem.php?pid=5527
思路: 对于这个题比较难的点就是在 50 和 500 的处理上,因为如果没有50 和 500 的钱币 ,那么其他的钱币就是相互对立的。我就可以直接贪心的来找了。在这里处理的时候,我可以把 两张50的看成 1张100 的,500 同理。那么我考虑反方向也就是求 所有钱的价值- 我要凑的价值, 我要凑这个数的最小钱币数, 那么我在这里枚举 50 和 500 的奇偶情况,这样就可以贪心了。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf =0x3f3f3f3f;
int val[15]={0,1,5,10,20,50,100,200,500,1000,2000};
int cnt[15];
int tmpc[15];
int Ans;
int aim;
int solve(int sum)
{
int ans=0;
for(int i=10;i>=1;i--){
if(i==5|i==8){
int c=min(sum/(val[i]*2),tmpc[i]/2);
ans+=c*2;
sum-=val[i]*2*c;
}
else{
int c=min(tmpc[i],sum/val[i]);
ans+=c;
sum-=c*val[i];
}
if(sum<=0) break;
}
if(sum==0) return ans;
else return inf;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&aim);
int sum=0;
int tot=0;
for(int i=1;i<=10;i++){
scanf("%d",&cnt[i]);
tot+=cnt[i];
sum+=cnt[i]*val[i];
}
if(sum<aim){
printf("-1\n");
continue;
}
Ans=inf;
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
for(int k=1;k<=10;k++) tmpc[k]=cnt[k];
int tt=sum-aim;
if(tmpc[5]&&i==1){
tmpc[5]--;
tt-=val[5];
}
if(tmpc[8]&&j==1){
tmpc[8]--;
tt-=val[8];
}
//cout<<"**** tt "<<tt<<endl;
if(tt>=0) Ans=min(Ans,i+j+solve(tt));
}
}
if(Ans==inf) printf("-1\n");
else printf("%d\n",tot-Ans);
}
return 0;
}