zoukankan      html  css  js  c++  java
  • POJ 3040 Allowance 贪心

    这题目的贪心思路还是有一点细节问题的。

    还没有证明,据说是因为题目给的条件是每个价格是比它小的价格的倍数才能这么贪心的。

    思路如下:

    假设要给奶牛的钱为C

    1)从大面值到小面值一次拿钱,能拿多少拿多少。

    但是注意不能拿到的钱的总和大于C

    2)如果第一步拿到的钱不够C,那么就从小面值到大面值拿钱,能拿多少拿多少。

    直到拿到的钱总和大于等于C

    我刚开始第一步实现的比较好,但是第二步想错了。

    后来才意识到大拿到的钱尽量不要超过C很多才是最优的,所以第二步要从小到大拿

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <set>
    #include <queue>
    #include <algorithm>
    #define MAXN 11111
    #define MAXM 222222
    #define INF 1000000000
    using namespace std;
    int n, c;
    typedef pair<int, int> P;
    P a[22];
    int use[22], sum[22];
    int main()
    {
        scanf("%d%d", &n, &c);
        for(int i = 0; i < n; i++) scanf("%d%d", &a[i].first, &a[i].second);
        sort(a, a + n);
        int ans = 0;
        for(int i = n - 1; i >= 0; i--)
            if(a[i].first >= c)
            {
                ans += a[i].second;
                a[i].second = 0;
            }
        while(true)
        {
            int flag = 0;
            int tmp = c;
    
            memset(use, 0, sizeof(use));
            for(int i = n - 1; i >= 0; i--)
                if(a[i].second)
                {
                    int k = tmp / a[i].first;
                    int mi = min(a[i].second, k);
                    tmp -= mi * a[i].first;
                    use[i] = mi;
                    if(tmp <= 0)
                    {
                        flag = 1;
                        break;
                    }
                }
            if(tmp > 0)
            {
                for(int i = 0; i < n; i++)
                    if(a[i].second > use[i])
                    {
                        while(use[i] < a[i].second)
                        {
                            tmp -= a[i].first;
                            use[i]++;
                            if(tmp <= 0)
                            {
                                flag = 1;
                                break;
                            }
                        }
                        if(tmp <= 0) break;
                    }
            }
            if(!flag) break;
            int mx = INF;
            for(int i = n - 1; i >= 0; i--)
            if(use[i]) mx = min(mx, a[i].second / use[i]);
            ans += mx;
            for(int i = n - 1; i >= 0; i--)
                if(use[i]) a[i].second -= mx * use[i];
    
        }
        printf("%d
    ", ans);
        return 0;
    }
    


  • 相关阅读:
    第一阶段冲刺 第三天
    第一阶段冲刺 第二天
    第一阶段冲刺 第一天
    第十周进度表
    第九周进度表
    NABCD需求分析
    典型用户和场景分析
    第一个冲刺周期-第一天
    第十周进度表
    团队电梯演讲视频链接
  • 原文地址:https://www.cnblogs.com/riskyer/p/3279823.html
Copyright © 2011-2022 走看看