HDU6685 Rikka with Coin

题意

给无限个10,20,50,100的硬币,以及n(<=100)个价格,问最少带多少硬币能表示任意一个价格。

思路

10元硬币一定不超过1个,20元不超过4个,50元不超过1个。枚举每种硬币出现的次数,做一次01背包求出那些价格可以被表示,能拼出的价格范围在0~140之间。对于每个价格w,取x=w%100,如果100+x能被表示,就最少需要w/100-1个100元硬币,如果x能被表示就最小需要w/100个100元硬币,否则就不能被表示。

#include<bits/stdc++.h>
using namespace std;

int n;
int a[105],b[105];
int f[305];

int solve(int x,int y,int z)
{
    int num=0;
    for (int i=1;i<=x;i++) b[++num]=10;
    for (int i=1;i<=y;i++) b[++num]=20;
    for (int i=1;i<=z;i++) b[++num]=50;
    memset(f,0,sizeof(f));
    f[0]=1;
    for (int i=1;i<=num;i++)
    {
        for (int j=150;j>=0;j-=10)
        {
            if (f[j]) f[j]=1;
            if (j-b[i]>=0&&f[j-b[i]]) f[j]=1;
        }
    }
    int cur=0;
    for (int i=1;i<=n;i++)
    {
        if (a[i]<=150&&f[a[i]]) continue;
        if (f[a[i]%100+100])
        {
            cur=max(cur,a[i]/100-1);
            continue;
        } else
        if (f[a[i]%100]) cur=max(cur,a[i]/100); else return 1000000000;
    }
    return cur+x+y+z;
}

int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        bool jud=0;
        for (int i=1;i<=n;i++)
        {
            if (a[i]%10) jud=1;
        }
        if (jud)
        {
            printf("-1
");
            continue;
        }
        int ans=1000000000;
        for (int i=0;i<=1;i++)
        {
            for (int j=0;j<=4;j++)
            {
                for (int k=0;k<=1;k++)
                {
                    ans=min(ans,solve(i,j,k));
                }
            }
        }
        printf("%d
",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/zhanggengchen/p/11385054.html