PAT A1056 Mice and Rice

PAT A1056 Mice and Rice

在这里插入图片描述在这里插入图片描述

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
  • 分析:
    which is a permutation of 0,⋯,N​P​​−1第3行给出的是各位选手的出场顺序,每个数代表一个选手编号
    按顺序,每Ng个人分一组(if there are less than N​G​​ mice at the end of the player's list, then all the mice left will be put into the last group.),每组决出一个胜者,胜者继续分组决斗,直到只剩一个人

  • 思路 1:
    输出每个人的排名,由于每一组只选一个冠军:所以上一轮的组数,就是本轮的参赛人数,由此逆推可知,第n轮失败者的排名就是第
    n轮胜者的个数+1,而胜者的个数又等于第n轮的组数
    由此可得到思路 :
    用一个队列实现比赛的先后顺序
    每轮循环先求出组数,并将本轮所有参赛者的排名赋值为组数,失败者出队,胜者加入队尾参与下一轮,如此循环到队列中只剩一个元素(通过判断跳出循环,不加判断的话,这个元素会反复出队入队)

  • code 1:

#include <iostream>
#include <stdio.h>
#include <queue>
using namespace std;
const int maxn = 1010;
queue<int> win;
int order[maxn];
struct mouse{
	int weight, ra;
}mou[maxn];
int main(){
	int np, ng;
	scanf("%d %d", &np, &ng);
	for(int i = 0; i < np; ++i){
		scanf("%d", &mou[i].weight);
	}
	for(int i = 0; i < np; ++i){
		scanf("%d", &order[i]);
	}
	for(int i = 0; i < np; ++i){
		win.push(order[i]);
	} 
	int numG, tmp = np;
	while(!win.empty()){
		//求出每轮的组数 
		if(tmp % ng == 0) numG = tmp / ng;
		else numG = tmp / ng + 1;
		int idex = 0, winner;
		while(idex < tmp){
			winner = 0;
			int Max = 0, cnt = ng;
			while(cnt > 0 && idex < tmp){
				int now = win.front();
				win.pop();
				mou[now].ra = numG + 1;
				if(mou[now].weight > Max){
					Max = mou[now].weight;
					winner = now;
				}
				cnt--; idex++;
			}
			win.push(winner);
		}
		tmp = numG;
		if(tmp == 1){
			mou[winner].ra = 1;
			break;
		}  
	}
	for(int i = 0; i < np; ++i){
		printf("%d", mou[i].ra);
		if(i < np-1) printf(" ");
	}
	return 0;
}

  • T2 code:
#include <bits/stdc++.h>
#include <queue>
using namespace std;
const int maxn = 1010;
int players[2][maxn];	//0: weight 1:rank 

int main(){
	int np, ng;
	scanf("%d %d", &np, &ng);
	for(int i = 0; i < np; ++i){
		scanf("%d", &players[0][i]);
	}
	queue<int> win, fail;
	for(int i = 0; i < np; ++i){
		int now;
		scanf("%d", &now);
		win.push(now);
	}
	int sum = np;
	while(sum != 1){
		sum = ceil(1.0 * sum / ng);
		int i = 0, j = 0, len = win.size();
		while(j < len){
			int winner = -1, Max = -1;
			while(j < len && j - i < ng){
				int tmp = win.front();
				players[1][tmp] = sum + 1;
				win.pop();
				if(players[0][tmp] > Max){
					Max = players[0][tmp];
					winner = tmp;
				}
				j++;
			}
			win.push(winner);
			i = j;
		}
	}
	int final_winner = win.front();
	players[1][final_winner] = 1;
	for(int i = 0; i < np; ++i){
		if(i == 0) printf("%d", players[1][i]);
		else printf(" %d", players[1][i]);
	}
	return 0;
} 
  • T3 code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2020;  //要开大点,因为队列一直向一个方向伸长
int weight[maxn], ranklist[maxn], Q[maxn], f = -1, r = -1;

bool Empty(){ return f == r ? true : false; }
void Push(int x){ Q[++r] = x; }
void Pop(){ f++; }
int Top(){ if(!Empty()) return Q[f+1]; }
int Size(){ return r - f; }

int main()
{
    int np, ng;
    scanf("%d %d", &np, &ng);
    for(int i = 0; i < np; ++i)
    {
        scanf("%d", &weight[i]);
    }
    for(int i = 0; i < np; ++i)
    {
        int now_player;
        scanf("%d", &now_player);
        Push(now_player);
    }
    int num_round = np;
    while(Size() != 1)
    {
        int cnt = 0, num_group = ceil(1.0 * num_round / ng);
        for(int i = 0; i < num_group; ++i)
        {
            int Max = -1, winner = 0;
            for(int j = 0; j < ng; ++j)
            {
                int tmp = Top();
                if(weight[tmp] > Max)
                {
                    Max = weight[tmp];
                    winner = tmp;
                }
                ranklist[tmp] = num_group + 1;
                Pop();
                if(++cnt == num_round) break;
            }
            Push(winner);
        }
        num_round = num_group;
    }
    ranklist[Top()] = 1;
    for(int i = 0; i < np; ++i)
    {
        printf("%d", ranklist[i]);
        if(i < np - 1) printf(" ");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值