zoukankan      html  css  js  c++  java
  • noip模拟赛 天天寄快递

    分析:并不是特别难的一道题,用到了贪心算法.

          首先可以明确的一点是我们要尽量偷贡献最大的数据,要先满足每一个公司的贡献都大于等于K,以这个作为首要条件.那么我们可以先把每个快递公司的快递按照贡献从大到小排序,每次选贡献最大的,满足要求了就考虑下一个快递公司,如果过程中用超过了s个或者处理完后发现还有快递公司没有满足要求就输出无解.

          上面只是满足了第一个要求,这时可能s个还没有用满,那么我们在按照贡献全体排一次序,看哪些没有用加上去就好了.

    中途犯了一个很愚蠢的错误:直接把vis数组赋值为i,其实这是不对的,每一个vis应该对应快递的ID,而不是排序后的i!

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    int n, m, s, k;
    long long ans,tot, cnt, sum, cnt2;
    bool flag = false,can[200010];
    
    struct node
    {
        long long e, t;
        bool vis;
    }a[200010];
    
    bool cmp1(node a, node b)
    {
        if (a.e == b.e)
            return a.t < b.t; //实际上是看谁的贡献最大
        return a.e < b.e;
    }
    
    bool cmp2(node a, node b)
    {
        return a.t < b.t;
    }
    
    int main()
    {
        scanf("%d%d%d%d", &n, &m, &s, &k);
        for (int i = 1; i <= m; i++)
        {
            long long e, t;
            scanf("%lld%lld", &e, &t);
            if (2 - t < 0)
            {
                a[++tot].e = e;
                a[tot].t = 2 - t;
            }
        }
        sort(a + 1, a + 1 + tot, cmp1);
        if (a[tot].e < n)
        {
            printf("-23333333
    ");
            return 0;
        }
        for (int i = 1; i <= tot; i++)
        {
            if (can[a[i].e])
                continue;
            sum -= a[i].t;
            cnt++;
            a[i].vis = 1;
            if (cnt > s)
            {
                flag = 1;
                break;
            }
            if (sum >= k)
            {
                ans += sum;
                sum = 0;
                can[a[i].e] = 1;
            }
        }
        for (int i = 1; i <= n; i++)
            if (!can[i])
            {
                flag = 1;
                break;
            }
        if (flag)
            printf("-23333333
    ");
        else
        {
            sort(a + 1, a + tot + 1, cmp2);
            for (int i = 1; i <= tot; i++)
            {
                if (!a[i].vis)
                {
                    cnt++;
                    ans -= a[i].t;
                    if (cnt == s)
                        break;
                }
            }
            printf("%lld
    ", ans);
        }
    
        return 0;
    }
  • 相关阅读:
    JavaScript 把函数作为参数进行传值
    面向微服务的企业云计算架构转型
    bzoj1009 GT考试 (kmp+矩阵优化dp)
    noiac64 sort (二分答案)
    luogu1983 车站分级 (拓扑排序)
    loj6157 A ^ BProblem (并查集)
    bzoj1831 逆序对 (dp+树状数组)
    luogu2282/bzoj1219 历史年份 (dp+hash+二分+线段树)
    bzoj3702/bzoj2212 二叉树 (线段树合并)
    cf1073G Yet Another LCP Problem (SA+权值线段树)
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7581391.html
Copyright © 2011-2022 走看看