二叉堆_貪心_POJ1456_Supermarket
阿新 • • 發佈:2018-11-09
思路分析:
將所有商品按照保質期非遞減排序得序列A[1...n], 設H為初始為空的最小堆. 執行下述虛擬碼所述貪心過程:
for i = 1 to n
if A[i]的保質期 > H.size
H.push(A[i]的利潤)
else
if A[i].利潤 > H.top()
H.pop(), H.push(A[i]的利潤)
容易證明上述過程滿足迴圈不變式, i >= 2時, 每次第1行迴圈頭檢測之前, H中元素對應的集合為A[1...i - 1]中可獲得最大利潤的售出方案對應的售出商品集合.
下面給出AC程式碼:
//POJ1456_Supermarket #include <iostream> #include <cstdio> #include <queue> #include <algorithm> using namespace std; const int MAX = 1e4 + 5; pair<int, int> pro[MAX];//first:保質期, second:利潤 int main(){ int n; while(~scanf("%d", &n)){ for(int i = 1; i <= n; ++i) scanf("%d %d", &pro[i].second, &pro[i].first); sort(pro + 1, pro + n + 1); priority_queue<int> heap; for(int i = 1; i <= n; ++i) if(pro[i].first > heap.size()) heap.push(-pro[i].second); else if(pro[i].second > -heap.top()) heap.pop(), heap.push(-pro[i].second); int ans = 0; while(!heap.empty()) ans += -heap.top(), heap.pop(); cout << ans << endl; } return 0; }
另外, 本題使用muitiset也可直接AC, 程式碼如下:
//POJ1456_Supermarket #include <iostream> #include <cstdio> #include <set> #include <algorithm> using namespace std; const int MAX = 1e4 + 5; pair<int, int> pro[MAX];//first:保質期, second:利潤 int main(){ int n; while(~scanf("%d", &n)){ for(int i = 1; i <= n; ++i) scanf("%d %d", &pro[i].second, &pro[i].first); sort(pro + 1, pro + n + 1); multiset<int> heap; for(int i = 1; i <= n; ++i) if(pro[i].first > heap.size()) heap.insert(pro[i].second); else if(pro[i].second > *heap.begin()) heap.erase(heap.begin()), heap.insert(pro[i].second); int ans = 0; for(multiset<int>::iterator it = heap.begin(); it != heap.end(); ++it) ans += *it; cout << ans << endl; } return 0; }