我的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++解题报告: