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著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。

相關文章
相關標籤/搜索