PAT 7-39 魔法優惠券(優先隊列的使用)

本題考點:

  • 優先隊列的使用

在火星上有個魔法商店,提供魔法優惠券。每個優惠劵上印有一個整數面值K,表示若你在購買某商品時使用這張優惠劵,可以得到K倍該商品價值的回報!該商店還免費贈送一些有價值的商品,但是如果你在領取免費贈品的時候使用面值爲正的優惠劵,則必須倒貼給商店K倍該商品價值的金額…… 但是不要緊,還有面值爲負的優惠劵可以用!(真是神奇的火星) 例如,給定一組優惠劵,面值分別爲1、2、4、-1;對應一組商品,價值爲火星幣M$7、6、-2、-3,其中負的價值表示該商品是免費贈品。我們可以將優惠劵3用在商品1上,得到M$28的回報;優惠劵2用在商品2上,得到M$12的回報;優惠劵4用在商品4上,得到M$3的回報。但是如果一不小心把優惠劵3用在商品4上,你必須倒貼給商店M$12。同樣,當你一不小心把優惠劵4用在商品1上,你必須倒貼給商店M$7。 規定每張優惠券和每件商品都只能最多被使用一次,求你可以得到的最大回報。

本題是優先隊列的使用經典案例,我們將正數和負數分開存放,正數放到大頂堆中,負數放到小頂堆中,然後分別從兩個堆中去除對應的值相乘然後相加即可獲得最大值。

完整代碼如下:

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;

priority_queue<int> posiGoods, posiDiscounts;   // 正數採用大頂堆
priority_queue<int, vector<int>, greater<int>> negaGoods, negaDiscounts;    // 負數採用小頂堆

int main()
{
    int n, temp;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        scanf("%d", &temp);
        if (temp > 0)
            posiGoods.push(temp);
        else
            negaGoods.push(temp);
    }
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        scanf("%d", &temp);
        if (temp > 0)
            posiDiscounts.push(temp);
        else
            negaDiscounts.push(temp);
    }
    int sum = 0;
    while (!posiGoods.empty() && !posiDiscounts.empty())
    {
        sum += posiGoods.top() * posiDiscounts.top();
        posiDiscounts.pop();
        posiGoods.pop();
    }
    while (!negaGoods.empty() && !negaDiscounts.empty())
    {
        sum += negaGoods.top() * negaDiscounts.top();
        negaGoods.pop();
        negaDiscounts.pop();
    }
    printf("%d", sum);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章