1. 程式人生 > 實用技巧 >【堆】B002_AW_超市(貪心+最小堆)

【堆】B002_AW_超市(貪心+最小堆)

超市裡有N件商品,每件商品都有利潤pi和過期時間di,每天只能賣一件商品,過期商品不能再賣。
求合理安排每天賣的商品的情況下,可以得到的最大收益是多少。

輸入格式
輸入包含多組測試用例。
每組測試用例,以輸入整數N開始,接下來輸入N對pi和di,分別代表第i件商品的利潤和過期時間。
在輸入中,資料之間可以自由穿插任意個空格或空行,輸入至檔案結尾時終止輸入,保證資料正確。
輸出格式
對於每組產品,輸出一個該組的最大收益值。
每個結果佔一行。
資料範圍
0≤N≤10000,
1≤pi,di≤10000
最多有14組測試樣例

輸入樣例:
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

方法一:貪心+小根堆

每天只能賣出一種商品,首先時間得有序才能再對利潤做出決策,這裡先對時間升序排序;當遇到新商品 x 時,且第 j 天能賣的商品個數已經達到了 j 個(即加入該商品後是j+1個),那麼就對比商品 x 和這 1~j 天中利潤最小的商品的利潤,如果 x.p 大於它,那麼這個商品就不要了了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node{
    ll p, d;
};
bool cmp(const node &a, const node &b){
    return a.d < b.d;
}

const int N=1e5+5;
node A[N];
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int n;
    while (cin>>n) {
        for (int i=0; i<n; i++) cin>>A[i].p>>A[i].d;
        priority_queue<ll, vector<ll>, greater<ll>> minQ;
        sort(A, A+n, cmp);
        for (int i=0; i<n; i++) {
            minQ.push(A[i].p);
            if (minQ.size()>A[i].d) {
                minQ.pop();
            }
        }
        int ans=0;
        while (!minQ.empty()) {
            ans+=minQ.top(); minQ.pop();
        }
        cout << ans << '\n';
    }    
    return 0;
}

複雜度分析

  • Time\(O(nlogn)\)
  • Space\(O(n)\)