HDU5727(贪心)

来源:互联网 发布:ubuntu lamp环境搭建 编辑:程序博客网 时间:2024/06/05 13:43
分析:这个题可以反过来想。用最少的硬币把多出来的钱凑完。但是输入并不保证可以正好凑出来。所以必须考虑完不成的情况。因为10种面值里面只有50和500前面的面值不是他的因子(20和200)。所以得考虑是否把50和500都用完。因为50不能由20组成,500不能由200组成,所以每次搜索时要考虑全用或者留一个。从而保证结果最优!
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#include<iostream>#include<algorithm>#include<stack>#include<queue>#include<vector>#include<set>#include<map>#include<string>#define nl n<<1#define nr (n<<1)1using namespace std;typedef long long ll;typedef unsigned long long ull;typedef pair<int,int>P;const int INF=0x3f3f3f3f;const ll INFF=0x3f3f3f3f3f3f3f3f;const double pi=acos(-1.0);const double eps=1e-9;int f[]={0,1,5,10,20,50,100,200,500,1000,2000};int a[15];int fun(int mo,int me){    if(me==0)return 0;    if(mo==0)return -1;    int x1=INF,x2=INF;    int h=min(a[mo],me/f[mo]);    int tmp=fun(mo-1,me-f[mo]*h);    if(tmp!=-1) x1=tmp+h;    if(h>0)    {        tmp=fun(mo-1,me-f[mo]*(h-1));        if(tmp!=-1)            x2=tmp+h-1;    }    if(x1==INF&&x2==INF)return -1;    return min(x1,x2);}int main(){    int t;scanf("%d",&t);    while(t--)    {        int p;scanf("%d",&p);        int sum=0,tot=0;        for(int i=1;i<=10;i++)        {            scanf("%d",&a[i]);            sum+=a[i]*f[i];tot+=a[i];        }        int m=sum-p;        if(m<0){printf("-1\n");continue;}        int tmp=fun(10,m);        if(tmp==-1) printf("-1\n");        else printf("%d\n",tot-tmp);    }    return 0;}

原创粉丝点击