队列的应用

这篇博客介绍了如何利用队列解决一个关于老鼠比赛的问题。题目要求根据老鼠的质量和特定的分组规则,确定每只老鼠的排名。算法涉及计算每轮比赛的组数,以及如何晋级。博客详细阐述了解题思路,包括如何初始化结构体、处理每轮比赛以及注意点,最后提供了参考代码。

题意

给出NP只老鼠的质量,并给出它们的初始值顺序(具体见样例解释),按这个初始顺序把这些老鼠按每NG只分为一组,最后不够NG只的也单独分为一组。对每组老鼠,选出它们中质量最大的1只晋级,这样晋级的老鼠数就等于该轮分组的组数。对这些晋级的老鼠再按上面的步骤每NG只分为一组进行比较,选出质量最大的一批继续晋级,这样直到最后只剩下1只老鼠,排名为1.把这些老鼠的排名按原输入的顺序输出。

输入样例

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

样例解释

题目中给出的老鼠们的初始值顺序其实是编号的顺序,即6号老鼠排在第一个,0号老鼠拍在第二个,…,3号老鼠排在最后一个。这样初始时老鼠的顺序就是(用质量表示):

19 25 57 22 10 3 56 18 37 0 46

这样质量为57的老鼠排名第一,质量为46的老鼠排名第二,质量为22、56的老鼠排名并列第三。由于此时已经有4只老鼠了,因此接下来剩下的老鼠全部为第五名。
输出老鼠的排名时,按照原输入质量的顺序输出排名。

思路

步骤1:开一个结构体mouse,用以记录每只老鼠的质量和排名。
定义一个队列,用来在算法过程中按顺序处理每轮的老鼠。
步骤2:算出以下几个数据。
1、每轮比赛把老鼠分成的组数group:设当前轮的参赛老鼠数有temp只,如果temp%NG为0,那么说明能够把老鼠完整划分,因此group=temp/NG;否则,说明最后会有少于NG只老鼠会单独分为一组,此时组数group=temp/NG+1。
2、由于每组晋级1只老鼠,因此当前轮晋级的老鼠数等于group,且该轮未晋级的老鼠的排名均为group+1.
由此可以得到算法的大致轮廓:
1、用temp记录当前轮的参赛老鼠数(初始值为NP),group记录当前轮的组数,初始时把老鼠们的编号按顺序加入队列。
2、之后进入while循环,每一层循环代表一轮比赛。
3、对每一轮比赛,枚举队列内的当前轮的temp只老鼠,按每NG只老鼠一组选出组内质量最大的老鼠,并将其入队表示晋级,而当前轮老鼠的排名(即group+1)可在选出最大老鼠的过程中直接对每只老鼠都赋值(晋级的老鼠在下一轮比赛时会得到新的排名)。这样直接队列中只剩下1只老鼠,就把它的排名记为1。最后输出所有老鼠的排名。

注意点

1、样例之所以模拟不出来,一般都是因为对题目给出的初始顺序理解不正确,可以仔细体会“样例解释”部分的内容。
2、有些写法会使只有1个老鼠时其排名出错,一般可以在循环后单独将排名第一的老鼠的排名进行赋值。
3、在运行时输入数据弹出错误提示的原因一般是没有处理最后一组老鼠不足NG只的情况,即没有注意控制每轮老鼠的总数,导致某步在队列内没有老鼠却使用了q.front()取队首老鼠。
4、所有老鼠的质量保证不同。

参考代码

#include<cstdio>
#include<queue>

using namespace std;
const int maxn = 1010;
struct mouse//老鼠
{
	int weight;//质量
	int R;//排名
}mouse[maxn];
int main()
{
	int np, ng, order;
	scanf_s("%d%d", &np, &ng);//含义如题意
	for (int i = 0; i < np; i++)
	{
		scanf_s("%d", &mouse[i].weight);
	}
	queue<int> q;//定义一个队列
	for (int i = 0; i < np; i++)
	{
		scanf_s("%d", &order);//题目给出的顺序
		q.push(order);//按顺序把老鼠们的标号入队
	}
	int temp = np, group;//temp为当前轮的比赛总老鼠数,group为组数
	while (q.size()!=1)
	{//计算group,即当前轮分为几组进行比赛
		if (temp%ng==0)
		{
			group = temp / ng;
		}
		else
		{
			group = temp / ng + 1;
		}//枚举每一组,选出该组老鼠中质量最大的
		for (int i = 0; i < group; i++)
		{
			int k = q.front();//k存放该组质量最大的老鼠的编号
			
			for (int j = 0; j < ng; j++)
			{
				//在最后一组老鼠数不足NG时起作用,退出循环
				if (i*ng+j>=temp)
				{
					break;
				}
				int front = q.front();//队首老鼠编号
				if (mouse[front].weight>mouse[k].weight)
				{
					k = front;//找出质量最大的老鼠
				}
				mouse[front].R = group + 1;//该轮老鼠排名为group+1
				q.pop();//出队这只老鼠
			}
			q.push(k);//把胜利的老鼠晋级
		}
		temp = group;//group只老鼠晋级,因此下轮总老鼠数为group
	}
	mouse[q.front()].R = 1;//当队列中只剩1只老鼠时,令其排名为1
	//输出所有老鼠的信息
	for (int i = 0; i < np; i++)
	{
		printf("%d", mouse[i].R);
		if (i<np-1)
		{
			printf(" ");
		}
		
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值