• HDU 5527:Too Rich(DFS+贪心)***


    题目链接

    题意

    给出p块钱,现在要用十种硬币凑出,每种硬币有c[i]个,问最多能用多少个硬币。

    思路

    首先确定,对于每个硬币就是能用小的替换就不用大的。

    所以,可以先把硬币尽量用小的替换,如果小的不够用,再用大的去替换。

    根据这个思路,就可以处理出一个前 i 个硬币总价值的前缀和 pre[],从大的面额到小面额去枚举,当前这种面额的硬币至少需要使用 (sum - pre[i-1]) / val[i] 种,sum代表当前还剩下多少钱要去兑换,这个数要向上取整,然后继续dfs下去就可以了。

    还有一种情况,就是20和50的情况和200和500的情况,即20不能整除50,那么对于p=60,3个20硬币,1个50硬币这种样例就不能去用这种方法解决了。一个比较好的做法就是让这种硬币多用一个,让它的使用数量变成偶数,就可以被整除了。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> pii;
    const int INF = 0x3f3f3f3f;
    const int N = 15;
    int val[] = {0, 1, 5, 10, 20, 50, 100, 200, 500, 1000, 2000};
    int c[N], ans, pre[N];
    
    void dfs(int sum, int num, int rem) {
    	if(sum < 0) return ;
        if(rem == 0) {
            if(sum == 0) ans = max(ans, num);
            return ;
        }
        int tol = max(sum - pre[rem-1], 0); // 前面的硬币足够的话,就不使用现在的硬币
        int cur = (tol + val[rem] - 1) / val[rem]; // 向上取整
        if(cur <= c[rem]) dfs(sum - cur * val[rem], num + cur, rem - 1);
        cur++; // 当前面整除不了,需要多用一个,变成前面某一个的倍数,例如50和20,500和200
        if(cur <= c[rem]) dfs(sum - cur * val[rem], num + cur, rem - 1);
    }
    
    int main() {
    	int t; scanf("%d", &t);
    	while(t--) {
            int p; scanf("%d", &p);
            pre[0] = 0; ans = -1;
            for(int i = 1; i <= 10; i++)
    			scanf("%d", &c[i]), pre[i] = pre[i-1] + c[i] * val[i];
            dfs(p, 0, 10);
            printf("%d
    ", ans);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    正则表达式获取远程网页
    Devexpress 常见问题
    CSS 带显示隐藏左部页面按钮
    CSS 技巧积累
    SQL 常用操作
    重置 自增字段 起始值 和 步长
    Devexpress TreeList
    Devexpress GridControl
    JS常用
    ajax跨域请求
  • 原文地址:https://www.cnblogs.com/fightfordream/p/7676746.html
Copyright © 2020-2023  润新知