acwing 145. 超市

题面:ios

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

求合理安排天天卖的商品的状况下,能够获得的最大收益是多少。测试

输入格式

输入包含多组测试用例。优化

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

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

输出格式

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

每一个结果占一行。blog

数据范围

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\n", ans);
}
}

做者:米4达girl连接:https://www.acwing.com/solution/acwing/content/1350/来源:AcWing著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。

相关文章
相关标签/搜索