1. 程式人生 > >HDU - 5527 A - Too Rich (貪心&&dfs)

HDU - 5527 A - Too Rich (貪心&&dfs)

 連結:

http://acm.hdu.edu.cn/showproblem.php?pid=5527

題意:

給出硬幣面值和數量,讓你用數量最多的硬幣湊出給定的數.

思路:

正反思考都行.

正面想就是要儘可能多的用面值少的硬幣,所以從面值大的開始考慮,假設把比它面值小的都選上後,看看需要補多少個當前面值硬幣.

反面就是想去掉儘量少的硬幣,使得剩下的剛好滿足要求.

正:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int val[11] = {0, 1, 5, 10, 20, 50, 100, 200, 500, 1000, 2000};
ll sum[11];//字首和
int c[11];
int ans;
void dfs(int rest, int index,int cnt)//rest 剩下的錢 index 當前處理的面值下標 cnt 數量
{
    if(rest < 0 ) return ;
    if(index == 0)
    {
        if(rest == 0)
            ans = max(ans,cnt);
        return ;
    }
    ll cur = max(rest - sum[index - 1],(ll)0);  //減去價格小的硬幣價錢之和後可以由當前硬幣提供的價錢
    int curnum = cur / val[index]; //可以由當前硬幣提供的數量
    if(cur % val[index])//如果不能整出,那麼必然要加一
    {
        curnum++;
    }
    if(curnum <= c[index])
        dfs(rest - curnum * val[index], index - 1, cnt + curnum);
    curnum++;
    if(curnum <= c[index])
        dfs(rest - curnum * val[index], index - 1, cnt + curnum);
}
int main()
{
    int t,p;
    cin>>t;
    while(t--)
    {
        memset(sum,0,sizeof sum);
        ans = -1;
        cin>>p;
        for(int  i = 1; i <= 10; i++)
            cin>>c[i];
        for(int i = 1; i <= 10 ; i++)
        {
            sum[i] = sum[i-1] + val[i] * c[i];
        }
        dfs(p,10,0);
        cout<<ans<<endl;
    }
    return 0;
}

反:

# include <iostream>
# include <cstdio>
# include <cstring>
using namespace std;
typedef long long LL;
const LL INF = 0x3f3f3f3f3f3f3f3f;
LL a[]= {0,1,5,10,20,50,100,200,500,1000,2000}, b[13];
LL ans;
void dfs(int cur, LL tot, LL cnt)
{
    if(tot < 0) return;
    if(cur == 0)
    {
        if(tot == 0)
            ans = min(ans, cnt);
        return;
    }
    LL tmp = min((LL)b[cur], tot/a[cur]);
    dfs(cur-1, tot-tmp*a[cur], cnt+tmp);
    if(tmp) dfs(cur-1, tot-(tmp-1)*a[cur], cnt+tmp-1);

}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        LL tot = 0, sum = 0, all = 0;
        ans = INF;
        scanf("%lld",&sum);
        for(int i=1; i<=10; ++i) scanf("%lld",&b[i]), tot += a[i]*b[i], all += b[i];
        if(tot < sum)
        {
            puts("-1");
            continue;
        }
        dfs(10, tot-sum, 0);
        if(ans == INF) puts("-1");
        else
            printf("%lld\n",all-ans);
    }
    return 0;
}