PAT-ADVANCED1056——Mice and Rice
我的PAT-ADVANCED程式碼倉:https://github.com/617076674/PAT-ADVANCED
原題連結:https://pintia.cn/problem-sets/994805342720868352/problems/994805419468242944
題目描述:
題目翻譯:
1056 老鼠和大米
老鼠和大米是程式設計競賽的名稱,每個程式設計師必須編寫一段程式碼來控制給定地圖中老鼠的移動。每隻老鼠的目標是儘可能多地吃大米以成為胖老鼠。
首先,隨機決定NP個程式設計師的比賽順序。每NG個程式設計師在一組中進行比賽。一組中最胖的老鼠獲勝並進入下一回合。本回閤中的所有輸家排名都相同。每組中的獲勝者將進入到下一場比賽中,直到確定最終獲勝者。
為簡單起見,假設一旦程式設計師提交他/她的程式碼,每個老鼠的重量就固定了。 給出所有老鼠的重量和初始比賽順序,你需要輸出程式設計師的排名。
輸入格式:
每個輸入檔案包含一個測試用例。對每個測試用例,第一行包含2個正整數:NP和NG(<= 1000),分別代表程式設計師的數量和一組中的最大老鼠數量。如果在程式設計師列表的最後剩餘的老鼠數量小於NG,則剩下的所有小鼠將被放入最後一組。第二行包含NP個不同的非負數Wi(i = 0,⋯,NP - 1),Wi代表第i個老鼠的重量。第三行給出了初始比賽順序,即0,⋯,NP - 1的排列(假設程式設計師編號從0到NP - 1)。一行中的所有數字由一個空格分隔。
輸出格式:
對每個測試用例,在一行中列印最終排名。 第i個數字是第i個程式設計師的排名,並且所有數字必須用空格分隔,在行的末尾沒有額外的空格。
輸入樣例:
11 3
25 18 0 46 37 3 19 22 57 56 10
6 0 8 7 10 5 9 1 4 2 3
輸出樣例:
5 5 5 2 5 5 5 3 1 3 5
知識點:佇列、優先佇列
思路:按初始比賽順序入隊,並按NG進行分組各自進入一個優先佇列,取每個優先佇列的最高分數進入下一輪比賽佇列
時間複雜度是O(logNG(NP)log(NG)),其中logNG(NP)表示以NG為底NP的對數。空間複雜度是O(NP)。
C++程式碼:
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
struct programmer {
int id;
int data;
int rank;
friend bool operator < (programmer pg1, programmer pg2) {
return pg1.data < pg2.data;
}
};
bool cmp(programmer pg1, programmer pg2);
int main() {
int NP, NG, num;
scanf("%d %d", &NP, &NG);
programmer pgs[NP];
queue<programmer> programmers;
queue<programmer> tempProgrammers;
priority_queue<programmer> pqProgrammers;
for(int i = 0; i < NP; i++) {
pgs[i].id = i;
scanf("%d", &pgs[i].data);
}
for(int i = 0; i < NP; i++){
scanf("%d", &num);
programmers.push(pgs[num]);
}
vector<programmer> results;
int index = 0;
while(programmers.size() != 1){
int size = programmers.size(); //佇列programmers中的元素個數一直在變,提前記錄其個數
for(int i = 0; i < size; i += NG){
for(int j = i; j < i + NG && j < size; j++){
pqProgrammers.push(programmers.front());
programmers.pop();
}
tempProgrammers.push(pqProgrammers.top());
pqProgrammers.pop();
while(!pqProgrammers.empty()){
results.push_back(pqProgrammers.top());
pqProgrammers.pop();
}
}
while(!programmers.empty()){
programmers.pop();
}
while(!tempProgrammers.empty()){
programmers.push(tempProgrammers.front());
tempProgrammers.pop();
}
for(int i = index; i < results.size(); i++){
results[i].rank = programmers.size() + 1;
}
index = results.size();
}
programmers.front().rank = 1;
results.push_back(programmers.front());
sort(results.begin(), results.end(), cmp);
for(int i = 0; i < results.size(); i++){
printf("%d", results[i].rank);
if(i != results.size() - 1){
printf(" ");
}
}
}
bool cmp(programmer pg1, programmer pg2){
return pg1.id < pg2.id;
}
C++解題報告: