hdu5527
题目
你有一些面额的钱,要凑出p元而且钱数要尽量多。
思路
短小精悍的一道题,不过我还是绕啊绕的,先说我看别人的思路,就是反过来凑sum-p的最小数目,然后就是用贪心,但是并不是所有的小钱是它之前一项的约数,直接贪心并不正确,会有奇偶的分类,那我们就用搜索,同时记录用最多和少用一个即可,注意少用一个的前提是至少可以用一个。
感觉首先就是想不到反过来,还有就是是不是约数的影响,学习了orz
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
int f[11],a[11],p;
int fun(int mo,int me)
{
if(mo==0||me==0)
if(me==0)
return 0;
else
return -1;
int x1=0x3f3f3f3f;
int x2=0x3f3f3f3f;
int h=min(a[mo],me/f[mo]);
int temp=fun(mo-1,me-(f[mo]*h));
if(temp!=-1) x1=temp+h;
if(h>0)
{
temp=fun(mo-1,me-(f[mo]*(h-1)));
if(temp!=-1) x2=temp+h-1;
}
if(x1==0x3f3f3f3f&&x2==0x3f3f3f3f)
return -1;
else return min(x1,x2);
}
int main()
{
int T;
scanf("%d",&T);
f[1]=1,f[2]=5,f[3]=10,f[4]=20,f[5]=50,f[6]=100,f[7]=200,f[8]=500,f[9]=1000,f[10]=2000;
while(T--)
{
scanf("%d",&p);
int sum=0;
int tol=0;
for(int i=1; i<=10; i++)
{
scanf("%d",&a[i]);
tol+=a[i];
sum+=a[i]*f[i];
}
int m=sum-p;
if(m<0)
{
printf("-1\n");
continue;
}
int temp=fun(10,m);
if(temp==-1)
printf("-1\n");
else
printf("%d\n",tol-temp);
}
return 0;
}