Too Rich UVALive

需要求的是取p钱,使总的取得硬币数最大
反向思考就是求取sum-p的钱,使总的取的硬币数最少
这样贪心起来就容易了
从最大的开始 我们可以观察 除了20 50和200 500之外其余的相邻的2个之间都是倍数关系
所以特殊除了这2个就可以了
又因为20是50+50的倍数 所以在取50的时候要考虑少取一个50的情况(200 500同)
比如有3个50的时候 50+50是20的倍数可以表示 但如果是50*3的话无法用20表示 需要都跑一下

#include<bits/stdc++.h>

#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=a;i<=b;i++)

#define int long long

using namespace std;

int a[15]={0,1,5,10,20,50,100,200,500,1000,2000};
int mub[15],ans;

void dfs(int sum,int t,int now)
{
    if(sum==0)
    {
        ans=min(t,ans);
        return ;
    }
    if(now==0) return ;
    int m=sum/a[now];
    m=min(m,mub[now]);
    dfs(sum-m*a[now],t+m,now-1);
    if(m)
    {
        m--;
        dfs(sum-m*a[now],t+m,now-1);
    }

}
#undef int
int main()
{
#define int long long
    int t;
    cin>>t;
    while(t--)
    {
        ans=inf;
        int n,sum=0,all=0;
        cin>>n;
        rep(i,1,10) cin>>mub[i],sum+=a[i]*mub[i],all+=mub[i];
        sum=sum-n;
        if(sum>0)
            dfs(sum,0,10);
        cout<<(ans==inf?-1:all-ans)<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/minun/p/11504420.html