zoukankan      html  css  js  c++  java
  • POJ3040贪心

    题意:作为创纪录的牛奶生产的奖励,农场主约翰决定开始给Bessie奶牛一个小的每周津贴。FJ有一套硬币N种(1≤N≤20)不同的面额,每枚硬币是所有比他小的硬币面值的倍数,例如1美分硬币、5美分硬币、10美分硬币和50美分硬币。使用这些硬币,FJ每周至少给Bessie C(1 <= C <=100000000)美分。请你计算他最多能给Bessie几周。

    题解:

    ①因为数据量较大,所以不能采用单组模拟的方式,不然必会tle,因此设立了一个used[i]数组来存储一种贪心情况,各种硬币所需要的个数,以便将这种情况的总数一次性加在总周数上。

    ②贪心策略采用在满足先用大额面值,再用小额面值的前提下,先尽可能接近而不超过规定的津贴值;然后用从小额面值到大额面值,超过但尽可能少超过规定的津贴值进行贪心。

    注意:

    ①面值大于津贴的情况,直接在输入处预处理即可。 

    ②在考虑used数组时,不要大于本身的数量

    #include<stdio.h>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    const ll inf = 0x3f3f3f3f3f3f3f3f;
    struct coin {
        ll value;
        ll num;
    }p[30];
    bool cmp(coin a, coin b)
    {
        return a.value > b.value;
    }
    int main(void)
    {
        ios::sync_with_stdio(false);
        int N, C;cin >> N >> C;
        ll v, n, tot = 1;
        ll week = 0;
        for (ll i = 1; i <= N; i++)
        {
            cin >> v >> n;
            if (v >= C)
                week += n;
            else
            {
                p[tot].value = v;
                p[tot].num = n;
                tot++;
            }
        }
        sort(p + 1, p + 1 + tot, cmp);
        ll used[30];//存储一次贪心后的结果
        while (1)
        {
            memset(used, 0, sizeof(used));
            ll tmp = C;
            ll sum = 0;
            for (ll i = 1; i <= tot; i++)//贪心策略1,面额从大到小,尽可能接近C,但不超过
            {
                if (p[i].num == 0)continue;
                sum += p[i].num * p[i].value;
                used[i] = min(tmp / p[i].value, p[i].num);
                tmp -= used[i] * p[i].value;
            }
            if (sum < C)break;
            if (tmp != 0)//贪心策略2,面额从小到大,尽可能少超过C
            {
                for (ll i = tot; i >= 1; i--)
                {
                    if (p[i].num == 0)continue;
                    if (used[i] == p[i].num)continue;
                    while (used[i] < p[i].num)
                    {
                        used[i]++;
                        tmp -= p[i].value;
                        if (tmp <= 0)
                            break;
                    }
                    if (tmp <= 0)
                        break;
                }
            }
            ll Min_num = inf;//Min_num表示能执行的这一组used的总数
            for (ll i = 1; i <= tot; i++)
            {
                if (used[i] == 0)continue;
                Min_num = min(Min_num, p[i].num/used[i]);
            }
            week += Min_num;
            for (int i = 1; i <= tot; i++)
                p[i].num -= Min_num * used[i];
        }
        cout << week << endl;
        return 0;
    }
  • 相关阅读:
    enmo_day_07
    enmo_day_04
    enmo_day_05
    数据仓库的模型设计
    Lucene 概念,定义应用场景
    enum 枚举的简单应用
    单例模式&synchronized
    Spark的 DAGschedule & task schedule 区别以及相互联系
    Spark的stage & job & task 到底是什么 ,以及划分原理
    Java基本数据类型&引用类型总结
  • 原文地址:https://www.cnblogs.com/ZJNU-huyh/p/13224867.html
Copyright © 2011-2022 走看看