【PAT A1056】Mice and Rice


思路
模拟比赛这个应该不难,书里面是用一个队列,不难发现比赛的过程有点类似树的层次遍历,但它是从下往上遍历;我是用优先队列整,毕竟他有着只关注优先级最高的特点,符合题意。令我稍有点头疼的是名次,刚开始我是先把所有人的名词都设成1,然后用一个vector存败者,每轮比赛过后吧这个vector里的人的名次都加1,这明显不符题意,就像注释里说的就算3个人并列第一,第四个人也是第四名而不是第二,那么接下来的问题就是类似于排名了,而我预先弄的排名就像是分数,相同分数意味着相同名次,得根据这些分数重新排下名,想了好久没想出好办法,如果有朋友有好方法希望能指点下俺,感激不尽。不过书里很聪明,每轮的晋级者的个数加一刚好是这轮败者的名次,厉害啊!

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

struct programmer
{
	int rank;
	int weight;
}programmers[1010];

struct cmp {
	bool operator () (int A, int B){
		return programmers[A].weight < programmers[B].weight;
	}
};

int main(){
	//total num of programmers, num of programmers in one group
	int NP, NG;
	scanf("%d%d", &NP, &NG);
	for(int i = 0; i < NP; i++){
		scanf("%d", &programmers[i].weight);
		programmers[i].rank = 1;
	}
	//loser用来存储失败者的序号,winner用来存每轮的参赛者的序号
	vector<int> loser;
	queue<int> winner;
	for(int i = 0; i < NP; i++){
		int order;
		scanf("%d", &order);
		winner.push(order);
	}


	//如果参赛者大于1说明还有比赛,则继续循环,每一次循环是一轮比赛
	while(winner.size() > 1){
		int cnt = winner.size();
		//用优先队列来组织每一组比赛
		priority_queue<int, vector<int>, cmp> q;
		for(int i = 0; i < cnt; i++){
			q.push(winner.front());
			winner.pop();//参加了比赛就把他从参赛者中删除
			//组满了或者最后一组人数不够
			if(q.size() == NG || (q.size() > 0 && i == cnt - 1)){
				//每一组最大者进入下一轮
				winner.push(q.top());
				q.pop();
				//每一组的败者全部到loser里面去
				while(!q.empty()){
					loser.push_back(q.top());
					q.pop();
				}
			}
		}
		//没过完一轮,把败者的名词加1,注意这里假如3人并列第一,第四个人不是第四名
		//而是3人并列第一,第四人是第二名
		for(int i = 0; i < loser.size(); i++)
			programmers[loser[i]].rank++;
	}


	//重新修改名词,此时3人并列第一,第四人是第4名
	loser.push_back(winner.front());//把第一名也放进来,方便统一修改
	int max = programmers[loser[0]].rank;//表示要修改几轮
	int cnt = 0, before = 0;//cnt记录已经修改了多少人的名次,before是前面这些人是第几名
	//每次修改原名词为i的programmer
	for(int i = 1; i <= max; i++){
		while(cnt < loser.size() && programmers[loser[loser.size() - 1 - cnt]].rank == i){
			programmers[loser[loser.size() - 1 - cnt]].rank = before + 1;
			cnt++;
		}
		before = cnt;
	}

	//标准输出
	for(int i = 0; i < NP; i++){
		if(i == 0)
			printf("%d", programmers[i].rank);
		else
			printf(" %d", programmers[i].rank);
	}
	printf("\n");

	return 0;
}
发布了30 篇原创文章 · 获赞 1 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/lvmy3/article/details/104174812