zoukankan      html  css  js  c++  java
  • acwing 145. 超市

    题面:

    超市里有N件商品,每个商品都有利润pipi和过期时间didi,每天只能卖一件商品,过期商品(即当天di<=0di<=0)不能再卖。

    求合理安排每天卖的商品的情况下,可以得到的最大收益是多少。

    输入格式

    输入包含多组测试用例。

    每组测试用例,以输入整数N开始,接下里输入N对pipi和didi,分别代表第i件商品的利润和过期时间。

    在输入中,数据之间可以自由穿插任意个空格或空行,输入至文件结尾时终止输入,保证数据正确。

    输出格式

    对于每组产品,输出一个该组的最大收益值。

    每个结果占一行。

    数据范围

    0N100000≤N≤10000,
    1pi,di100001≤pi,di≤10000

    输入样例:

    4  50 2  10 1   20 2   30 1
    
    7  20 1   2 1   10 3  100 2   8 2
       5 20  50 10
    

    输出样例:

    80
    185
    题解:

    这道题目,我们很容易发现是有一个贪心性质,也就是对于t天,我们需要在保证不卖出过期商品的前提下,卖出利润前t大的商品.
    所以呢,我们可以把商品按照过期时间排序,然后建立一个小根堆,对于每一个数而言,如果说它的过期时间大于当前小根堆的个数,那么我们可以直接将这个货物的价值加入进来,如果说当前过期时间正好等于这个小根堆堆内的个数,那么我们就需要对比一下,如果说这个货物的价值,是高于小根堆的堆顶的话,那么我们就将小根堆堆顶弹出,然后push我们这个新货物,因为新货物明显是更加优于堆顶的老货物的

    代码:

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<vector>
    using namespace std;
    int main()
    {
        int n;
        while(cin>>n)
        {
            vector<pair<int,int> >pp(n);
            for(int i=0;i<n;i++)
             cin>>pp[i].second>>pp[i].first;
             sort(pp.begin(),pp.end());
             priority_queue<int,vector<int>,greater<int> >head;
             for(auto p:pp)
             {
                 head.push(p.second);
                 if(head.size()>p.first)head.pop();
             }
             int res=0;
             while(head.size())res+=head.top(),head.pop();
             cout<<res<<endl;
        }
        return 0;
    }

     法二:用并查集维护:(看的大佬的题解)

    贪心策略:
    在不过期的时间内优先卖出利润更大的产品。

    按照价值降序,每次扫描到一个价值,尝试一下在过期之前能不能卖出去;此时可能已经有比它更大价值的产品占用了一些日期,于是从过期时间往前面找,直到找到一个空位置。如果这个空位置大于0,那么就把这个产品安排在这天卖出。

    暴力找位置最坏复杂度可以达到O(n2)O(n2),所以用并查集优化,每个节点代表日期,日期记录他最近的前面的空闲日期是哪天,每次用掉这天就把这个点和前面的点连起来

    实测比优先队列快了三倍

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e4 + 233;
    typedef pair<int,int> pii;
    vector<pii> a;
    int f[maxn];
    int ff(int x)
    {
    if(f[x] == x) return x;
    return f[x] = ff(f[x]);
    }
    int main()
    {
    int n;
    while(cin >> n)
    {
    int ans = 0;
    a.clear();
    int maxe = 0;

    for(int i = 1; i <= n; i++)
    {
    int v,e;
    scanf("%d%d", &v, &e);
    a.push_back({-v, e});
    maxe = max(maxe, e);
    }
    for(int i = 0; i <= maxe; i++) f[i] = i;
    sort(a.begin(), a.end());
    for(int i = 0; i < a.size(); i++)
    {
    int v = -a[i].first, e = a[i].second;
    int pos = ff(e);
    if(pos > 0)
    {
    ans += v;
    f[pos] = pos - 1;
    }
    }
    printf("%d ", ans);
    }
    }

    作者:米4达girl
    链接:https://www.acwing.com/solution/acwing/content/1350/
    来源:AcWing
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 相关阅读:
    熟悉常用的Linux操作
    组合数据类型练习
    简易的词法分析程序
    大数据概述
    201552040205 关于对java的体验与感悟
    对已学习的java内容的一些感悟
    关于java中的一些小技巧
    Javase 大纲2
    Javase大纲
    MysQL知识整理
  • 原文地址:https://www.cnblogs.com/flyljz/p/11658563.html
Copyright © 2011-2022 走看看