PAT甲级真题及训练集(9)--1056. Mice and Rice (25)

1056. Mice and Rice (25)

时间限制
100 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Mice and Rice is the name of a programming contest in which each programmer must write a piece of code to control the movements of a mouse in a given map. The goal of each mouse is to eat as much rice as possible in order to become a FatMouse.

First the playing order is randomly decided for NP programmers. Then every NG programmers are grouped in a match. The fattest mouse in a group wins and enters the next turn. All the losers in this turn are ranked the same. Every NGwinners are then grouped in the next match until a final winner is determined.

For the sake of simplicity, assume that the weight of each mouse is fixed once the programmer submits his/her code. Given the weights of all the mice and the initial playing order, you are supposed to output the ranks for the programmers.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 positive integers: NP and NG (<= 1000), the number of programmers and the maximum number of mice in a group, respectively. If there are less than NG mice at the end of the player's list, then all the mice left will be put into the last group. The second line contains NP distinct non-negative numbers Wi (i=0,...NP-1) where each Wiis the weight of the i-th mouse respectively. The third line gives the initial playing order which is a permutation of 0,...NP-1 (assume that the programmers are numbered from 0 to NP-1). All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the final ranks in a line. The i-th number is the rank of the i-th programmer, and all the numbers must be separated by a space, with no extra space at the end of the line.

Sample Input:
11 3
25 18 0 46 37 3 19 22 57 56 10
6 0 8 7 10 5 9 1 4 2 3
Sample Output:
5 5 5 2 5 5 5 3 1 3 5

提交代

方案1:(pat测试运行结果正确,但是超时)

/**
作者:一叶扁舟
时间:21:40 2017/6/20
思路:
	1.首先计算总共要进行PK的总共轮次,9个老鼠要进行3轮次,10-27只老鼠要进行4轮
	28只老鼠要进行5轮,因此计算公式:m^k >= N; k+1轮,(m为每次m只老鼠进行比拼,N为N
	只老鼠)
	2.先将老鼠都都入队列,每次m个老鼠进行比拼,然后在入下一个队列,计算进入下一轮的老鼠个数,然后
	将上一轮老鼠的名次全部设置为进入下一轮老鼠数量+1,如总共有10老鼠,第一轮结束后,
	将有4只老鼠进入下一轮,因此将第一轮所有的老鼠的排名变为5(包括将进入下一轮的老鼠),以此类推。直到最后只剩下一只老鼠

*/
#include <stdio.h>
#include <string>
#include <stack>
#include <queue>
#include <math.h>    
using namespace std;
#define SIZE 10001

typedef struct Mouse{
	int weight;//老鼠的体重
	int num;//排名
}Mouse;
void updateRank(Mouse *allMouse, int  N, Mouse mouse, int rank){
	for (int i = 0; i < N; i++){
		if (allMouse[i].weight == mouse.weight){
			allMouse[i].num = rank;//修改排名
		}
	}
}
int main(){
	int N, M;//总共N只老鼠,每次M只老鼠比拼
	Mouse mouse[SIZE];
	queue<Mouse> q;//初始队列
	queue<Mouse> winQueue;//晋级队列
	queue<Mouse> markQueue;//对比拼过后的老鼠进行排名
	int weight;
	int num;
	int k = 0;//总共要进行的轮次

	scanf("%d %d", &N, &M);
	//计算总共要比拼的次数
	while (pow(M, k) <= N){
		k++;
	}
	k = k + 1;
	for (int i = 0; i < N; i++){
		scanf("%d", &weight);
		mouse[i].weight = weight;
		mouse[i].num = 0;//初始化排名
	}
	//清空队列
	while (!q.empty()){
		q.pop();
	}
	//清空晋级队列
	while (!winQueue.empty()){
		winQueue.pop();
	}
	for (int i = 0; i < N; i++){
		scanf("%d", &num);
		//进入操作的队列
		q.push(mouse[num]);
	}

	//核心,真正的开始进行晋级比拼了,总共要进行k轮比赛
	for (int i = 0; i < k; i++){
		while (!q.empty()){
			int j = 0;
			//取出第一只老鼠
			Mouse win = q.front();
			markQueue.push(q.front());
			q.pop();

			//每M只老鼠作为一个组
			for (int j = 0; j < M - 1 && !q.empty(); j++){
				Mouse next = q.front();
				markQueue.push(q.front());
					q.pop();
				if (next.weight >= win.weight){
					win.weight = next.weight;
					win.num = next.num;
				}
			}
			//此时win即为一组中胜出的老鼠,入队
			winQueue.push(win);
		}//一轮结束了

		int rank = winQueue.size();
		
		//对当前轮次的进行排名
		while (!markQueue.empty()){
	     	Mouse temp = 	markQueue.front();
			markQueue.pop();
			//修改排名
			updateRank(mouse, N, temp, rank + 1);
		}
		if (rank == 1){
			//当只有一只老鼠时,就说明比出了第一,所有的比拼结束了
			Mouse temp = winQueue.front();
			winQueue.pop();
			updateRank(mouse, N, temp, rank );
			break;
		}else{
			//将晋级队列中的数据转存到q队列中
			while (!winQueue.empty()){
				q.push(winQueue.front());
				winQueue.pop();
			}
		}
		
	
	}
	//输出结果
	for (int i = 0; i < N; i++){
		printf("%d",mouse[i].num);
		if (i != N - 1){
			printf(" ");
		}
	}
	system("pause");
	return 0;
}


方案2:(优化的结果,但是pat测试运行结果正确,仍是超时)

/**
作者:一叶扁舟
时间:17:23 2017/6/21
思路:
  上面的解决方案是正确的,但是在pat测试时,答案正确,超时了。说明时间复杂度比较大,因此在上面的基础上做优化
   本次优化方案从两个方面考虑:
   1.不在将每个老鼠数据(老鼠这个对象)放入到队列中,只将第一的编号放入队列中
        ,这样减少了,晋级时修改排名的所浪费的查找时间
   2.对于排名的计算方式采用了,当前轮次进行分的来计算
   3.更加1,2优化,再测试时发现仍然超时,因此又进行了第三次优化,将队列转存改为一个队列
     存储,通过使用一个count来终止一轮的结束,结果还是超时问题,无解了啊,这个我认为是最优解了
*/
#include <stdio.h>
#include <string>
#include <stack>
#include <queue>
#include <math.h>    
using namespace std;
#define SIZE 1000001

typedef struct Mouse{
	int weight;//老鼠的体重
	int num;//排名
}Mouse;
int main(){
	int N, M;//总共N只老鼠,每次M只老鼠比拼
	Mouse mouse[SIZE];
	queue<int> q;//初始队列
	int group;//每一轮所要分的组
	int weight;
	int num;
	int total;
	int k = 0;//总共要进行的轮次

	scanf("%d %d", &N, &M);
	//计算总共要比拼的次数
	while (pow(M, k) <= N){
		k++;
	}
	k = k + 1;
	for (int i = 0; i < N; i++){
		scanf("%d", &weight);
		mouse[i].weight = weight;
		mouse[i].num = 0;//初始化排名
	}
	//清空队列
	while (!q.empty()){
		q.pop();
	}
	for (int i = 0; i < N; i++){
		scanf("%d", &num);
		//只将下标编号放入队列中
		q.push(num);
	}

	//核心,真正的开始进行晋级比拼了,总共要进行k轮比赛
	for (int i = 0; i < k; i++){
		total = q.size();//本轮循环的总共个数
		int count = 0;//用来标识本轮已经出队的个数
		if (q.size() % M == 0){//所有恰好老鼠能够分到一个组中
			group = q.size() / M ;
		}
		else{
			group = q.size() / M + 1; 
		}
		while (!q.empty()){
			int j = 0;
			//取出第一只老鼠
			int win = q.front();
			q.pop();
			count++;
			mouse[win].num = group + 1;//当前轮次比赛出队列就可以修改排名了


			//每M只老鼠作为一个组
			for (int j = 0; j < M - 1 && count < total; j++){
				int next = q.front();
			     	q.pop();
					count++;
					mouse[next].num = group + 1;//当前轮次比赛出队列就可以修改排名了
				if (mouse[next].weight >= mouse[win].weight){
					win= next;
				}
			}
			//再入队列队尾
			q.push(win);
			if (count == total){
				break;
			}
		}//一轮结束了

		int rank = q.size();
		if (rank == 1){
			//当只有一只老鼠时,就说明比出了第一,所有的比拼结束了
			int temp = q.front();
			q.pop();
			mouse[temp].num = 1;
			break;
		}
	}
	//输出结果
	for (int i = 0; i < N; i++){
		printf("%d", mouse[i].num);
		if (i != N - 1){
			printf(" ");
		}
	}
	system("pause");
	return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值