從大理高中畢業後已過了 20 個年頭,當年的班長標哥今年決定舉辦一場老同學餐會,大家有機會重新聚聚,暢飲暢聊。
總共來了 N 位同學,餐飲總共上了 M 道菜,會餐前大家已事先講好,每道菜上菜時就由當時在座同學中
身上最有錢的同學支付該道菜的金額,如果最有錢的同學金額不足,則依次由下一位有錢的同學支付不足的款項。
當然,如果所有同學的金錢總和不足以支付所有的菜餚費用,唉! 那就尷尬了 !
範例測資
範例輸入 | 範例輸出 |
---|---|
EOF 輸入 (<= 100 筆),每筆測資 3 行,第一行有整數 N 和 M (1 <= N、M <=1,0000), 第二行有 N 個整數,代表一開始每位同學身上攜帶的金額,第三行有 M 個整數,依序代表每一道菜的應付金額。 | 每筆測資一行輸出,兩個整數, 代表一開始最有錢的同學的金額數, 及最後用餐完畢時最有錢的同學的金額數。 如果不夠支付餐點金額則輸出「Oh My God」。 |
3 4 100 200 300 200 200 200 200 5 7 1500 1500 1000 2000 3000 900 600 200 350 1200 400 1000 | Oh My God 3000 1450 |
解題思路
可以使用 Priority_Queue 來將每個人持有的金額存進去,存資料時可以使用 .push(金額)。當要取資料時,可以使用 .top(),就會回傳目前最大值。
使用 While迴圈,如果目前最大金額可以支付目前的菜,就將最大金額 -= 菜的價錢,不能使用 .top() -= 菜的價錢,所以可以將一個變數設定為 .top(),然後將這個變數 -= 菜的價錢,然後使用 .pop(),這樣會將資料中最大的金額刪除,並且重新 .push(剛剛進行減法的變數)。如果不夠支付金額,則用剛剛的辦法,只是這次將變數歸零,並且將目前菜的價錢 -= 最大金額,然後繼續跑 While迴圈。
可以設定一個布林值判斷是否要輸出「Oh My God」,如果已經完蛋了之後的 For迴圈只要收到資料之後都可以直接 Continue。
範例程式碼-ZeroJudge F631: 同學會
#include <iostream>
#include <queue>
using namespace std;
int main() {
cin.sync_with_stdio(0);
cin.tie(0);
int N, M;
while (cin >> N >> M)
{
priority_queue<int>num;
for (int i = 0; i<N; i++)
{
int tmp;
cin >> tmp;
num.push(tmp);
}
int first = num.top();
bool god = false;
for (int i = 0; i<M; i++)
{
int tmp, count = N-1;
cin >> tmp;
if (god) continue;
while (count >= 0)
{
if (num.top() >= tmp)
{
int t = num.top();
t -= tmp;
num.pop();
num.push(t);
tmp = 0;
break;
}
tmp -= num.top();
num.pop();
num.push(0);
count--;
}
if (tmp > 0) god = true;
}
if (god) cout << "Oh My God\n";
else cout << first << " " << num.top() << "\n";
}
}
//ZeroJudge F631
//Dr. SeanXD