• Rikka with coin 思维题


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6685

    题意:用面额分别为10,20,50,100的四种硬币组成n(n<=100)个数(wi<=1e9),求问最少需要多少硬币

    输入:
    The first line of the input contains a single integer T(1T500), the number of test cases.

    For each test case, the first line contains a single integer n(1n100), the number of combos sold in the canteen.

    The second line contains n positive integers w1,,wn(1wi109), which represents the prices.

    分析:

    首先 10分的硬币多只会用一个,如果用了两个,直接替换成一个 10分一个 20分一定不亏。(两个10分表示的数是一个20一个10表示的数的子集)
    20分的硬币多只会用三个,如果用了四个,直接替换成一个 10分两个20  分一个 50分一定不亏。

    50分的硬币多只会用一个,如果用了两个,直接替换成一个 50分和一个1元一定不亏。

    对于任何一种情况,重复使用上述规则一定会达到一个 10分硬币最多一个, 20分最多三个, 50分最多一个的情况,不会陷入重复甩锅的死循环。
    因此枚举这三种硬币分别用了多少个,然后整百的部分直接用一元硬币填,取少的答案就行了。

    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <map>
    #include <set>
    using namespace std;
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    const int N=1100,lim=40;
    int A[N],n,ans=1e9,pd[lim+10];
    const int w[4]={1,2,5,10};
    const int num[4]={1,3,1,3};
    void put(int k){
        for (int i=lim;i>=k;i--) pd[i]|=pd[i-k];
    }
    int calc(){
        int w=0;
        for (int i=1;i<=n;i++){
            int k=A[i]%10;
            int num=1e9;
            while (k<=lim&&k<=A[i]){
                if (pd[k]) num=min(num,(A[i]-k)/10);
                k+=10;
            }
            w=max(w,num);
        }
        return w;
    }
    void getans(int k,int tot){
        if (k==4){
            ans=min(ans,calc()+tot); return;
        }
        int back[lim+10]; memcpy(back,pd,sizeof pd);
        for (int i=0;i<=num[k];i++){
            getans(k+1,tot+i); put(w[k]);
        }
        memcpy(pd,back,sizeof back);
    }
    void solve(){
        scanf("%d",&n);
        for (int i=1;i<=n;i++){
            scanf("%d",&A[i]);
        }
        for (int i=1;i<=n;i++){
            if (A[i]%10){
                printf("-1
    "); return;
            }
            A[i]/=10;
        }
        ans=1e9; memset(pd,0x00,sizeof pd); pd[0]=1;
        getans(0,0);
        printf("%d
    ",ans);
    }
    int main(){
        int t; scanf("%d",&t);
        for (;t;t--) solve();
        return 0;
    }
  • 相关阅读:
    es6常见特性
    js实现查找字符串出现最多的字符和次数
    jQuery 插件封装的方法
    js变量作用域--变量提升
    js 三元表达式的写法
    bug
    基于bootstrap的模态框的comfirm弹窗
    基于bootstrap模态框的alert弹窗
    回车键搜索代码 兼容性
    盒子垂直居中方式
  • 原文地址:https://www.cnblogs.com/qingjiuling/p/11381028.html
Copyright © 2020-2023  润新知