HDU 5527 Too Rich (贪心+DFS)

题意:

有1,5,10,20,50,100,200,500,1000,2000十种面值的钱币各ci个,现在要凑出p元,问最多可以用多少钱币凑出

思路:

取最多的钱币,就是要多取面额小的钱币。
从小贪心到大面额,存在一个问题:
例如:
110 19个1 2个20 2个50这组数据
我们无法正确的从1开始贪心,以保证贪心的结果是正确的。
那么,我们可以转化一下思路多取面额小的钱币即少取面额大的。即在小面额的钱数足够时,能不用大面额的钱币就不用。
注意到除了20 50,200 500外,所有小面额钱币都是大面额钱币的因子,即大面额钱币都可以被足够多的小面额钱币代替,故每次取大面额钱币是独立的。
对于20 50,200 500我们可以将50 ,500转化为100,1000,通过枚举多取一张来保证操作的独立性。

代码:

#include <bits/stdc++.h>
using namespace std;
long long a[11];
long long b[11]={0,1,5,10,20,50,100,200,500,1000,2000};
long long sum[10];
long long ans,tempans,n;
void dfs(long long left,int pos){
    if(left<0) return ;
    if(pos==0){
        if(left==0) ans=max(ans,tempans);
        return ;
    }
    long long sub=max(0LL,left-sum[pos-1]);
    long long need=sub/b[pos];
    if(sub%b[pos]) need++;
    if(a[pos]>=need){
        tempans+=need;
        dfs(left-need*b[pos],pos-1);
        tempans-=need;
    }
    //for 20 50 200 500
    need++;
    if(a[pos]>=need){
        tempans+=need;
        dfs(left-need*b[pos],pos-1);
        tempans-=need;
    }
    return ;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%lld",&n);
        for(int i=1;i<=10;i++) scanf("%lld",&a[i]);
        sum[0]=0;
        for(int i=1;i<=10;i++) sum[i]=sum[i-1]+b[i]*a[i];
        ans=-1;
        tempans=0;
        dfs(n,10);
        printf("%lld\n",ans);
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值