【PAT甲级】1056 Mice and Rice (25分)

解题过程的小记录,如有错误欢迎指出。

难度:五星(题目读了好几遍也没读懂,不过看了解析后决定自己就算看懂题目可能也做不出来orz)

题目分析

第一行给出的是总共的老鼠数和每一组老鼠的数量
第二行给出的是每只老鼠的数量
第三行给出的是每只老鼠的编号
按给出的顺序分组,选出每一组中体重最大的老鼠晋级下一轮,下一轮再次进行分组,一直进行循环,知道找到第一名(第一名一定是所有老鼠中最重的,但第二名不一定是所有老鼠中第二重的)

注意点

  1. 第三行给出的是老鼠的编号
  2. 老鼠按照给出的老鼠编号,从左到右进行分组(给出编号是为了,按照编号去第二号找对应的重量)

我的解题过程

思路

  1. 把第二行的信息存入老鼠数组(是一个结构体数组,里面包含了体重和排名)
  2. 把第三行信息存入队列,从队首到队尾是按顺序成组比较的
  3. 设置变量保存当前剩余的需要比较的老鼠数和成组数
  4. 当队列不为1时(说明最大的老鼠数还没有找出来,还可以进行分组),进行分组找出每一组中体重最大的老鼠数,插入队列尾
  5. 进行一轮比赛就可以为所有参加这一轮比赛的老鼠进行排名的赋值,无论这一轮是否晋级,参加了这一轮就说明上一轮晋级了,所以可以赋值为group+1
  6. 当队列中只有一个老鼠编号时,为其排名赋值为1
  7. 按照编号顺序进行输出排名

bug

无从谈bug,完全写不来,代码是看着晴神的代码copy的,按照自己的代码风格略做了修改

代码

#include<iostream>
#include<queue>
#include<vector>

using namespace std;

struct mouse {
	int weight, rank;
};

int main()
{
	int np, ng;//参加比赛人数和一组拥有的最多人数
	scanf("%d %d\n", &np, &ng);
	vector<mouse> mice(np);
	for (int i = 0; i < np; i++) {
		scanf("%d", &mice[i].weight);
	}
	queue<int> q;//定义一个队列
	int order;
	for (int i = 0; i < np; i++) {
		scanf("%d", &order);//题目中给出的老鼠的标号
		q.push(order);//按顺序把老鼠们的标号入队
	}
	int left = np, group;//left为当前轮的比赛总老鼠数,group为组数
	while (q.size() != 1) {
		//计算group,即当前轮分为几组进行比赛
		if (left%ng == 0) group = left / ng;//最后一组也人数刚好
		else group = left / 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 >= left) break;
				int front = q.front();//队首老鼠编号
				if (mice[front].weight > mice[k].weight) {
					k = front;//找出质量最大的老鼠的编号
				}
				mice[front].rank = group + 1;//该轮老鼠排名为group+1
				q.pop();//把队首的这只老鼠出队
			}
			q.push(k);//把找出的质量最大的老鼠的编号插入队尾
		}
		left = group;//剩下的老鼠数为每一组的晋级老鼠数量,共有group个组,所以有group只老鼠晋级
	}
	mice[q.front()].rank = 1;//当队列中只有1只老鼠时,令其排名为1
	//输出所有老鼠的信息
	for (int i = 0; i < np; i++) {
		if (i != 0) printf(" ");
		printf("%d", mice[i].rank);
	}
    return 0;
}

dalao的代码

全部代码因版权原因不放出来,大家可以自行去柳神博客购买或者参考晴神的上机笔记~

借鉴点

本题看本篇解析代码即可,因为代码就是copy大佬的,如果看不懂可以去看晴神的分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值