pat basic 1115 裁判机

有一种数字游戏的规则如下:首先由裁判给定两个不同的正整数,然后参加游戏的几个人轮流给出正整数。要求给出的数字必须是前面已经出现的某两个正整数之差,且不能等于之前的任何一个数。游戏一直持续若干轮,中间有写重复或写错的人就出局。

本题要求你实现这个游戏的裁判机,自动判断每位游戏者给出的数字是否合法,以及最后的赢家。

输入格式:

输入在第一行中给出 2 个初始的正整数,保证都在 [1,105] 范围内且不相同。

第二行依次给出参加比赛的人数 N(2≤N≤10)和每个人都要经历的轮次数 M(2≤M≤103)。

以下 N 行,每行给出 M 个正整数。第 i 行对应第 i 个人给出的数字(i=1,⋯,N)。游戏顺序是从第 1 个人给出第 1 个数字开始,每人顺次在第 1 轮给出自己的第 1 个数字;然后每人顺次在第 2 轮给出自己的第 2 个数字,以此类推。

输出格式:

如果在第 k 轮,第 i 个人出局,就在一行中输出 Round #k: i is out.。出局人后面给出的数字不算;同一轮出局的人按编号增序输出。直到最后一轮结束,在一行中输出 Winner(s): W1 W2 ... Wn,其中 W1 ... Wn 是最后的赢家编号,按增序输出。数字间以 1 个空格分隔,行末不得有多余空格。如果没有赢家,则输出 No winner.。

输入样例 1:

101 42
4 5
59 34 67 9 7
17 9 8 50 7
25 92 43 26 37
76 51 1 41 40

输出样例 1:

Round #4: 1 is out.
Round #5: 3 is out.
Winner(s): 2 4

输入样例 2:

42 101
4 5
59 34 67 9 7
17 9 18 50 49
25 92 58 1 39
102 32 2 6 41

输出样例 2:

Round #1: 4 is out.
Round #3: 2 is out.
Round #4: 1 is out.
Round #5: 3 is out.
No winner.

解题思路:

这个算法不算很好,差一点点就超时了

#include <stdio.h>
#include <stdlib.h>
#define MAXA 100008
#define MAXN 10000
#define MAXM 1000

typedef enum { false, true } bool;
typedef struct node {
    int numbers[MAXM];
    bool isOut;
} Player;

bool isPass(int num, int isGiven[], int passedNumbers[], int passedEnd) {
    int i, j;

    if ( isGiven[num] )
        return false;
    for ( i=0; i<passedEnd-1; ++i )
        for ( j=i+1; j<passedEnd; ++j )
            if ( num == abs(passedNumbers[i] - passedNumbers[j]) )
                return true;

    return false;
}

int main(int argc, const char *argv[]) {
    int i, j, N, M, passedEnd = 2;
    int passedNumbers[MAXN] = {0,};
    int isGiven[MAXA] = {0,};

    if ( scanf("%d %d", &passedNumbers[0], &passedNumbers[1])==EOF ) printf("error\n");
    if ( scanf("%d %d", &N, &M)==EOF ) printf("error\n");
    isGiven[passedNumbers[0]] = 1;
    isGiven[passedNumbers[1]] = 1;
    Player players[N];
    for ( i=0; i<N; ++i ) {
        for ( j=0; j<M; ++j )
            if ( scanf("%d", &players[i].numbers[j])==EOF ) printf("error\n");
        players[i].isOut = false;
    }

    for ( j=0; j<M; ++j ) {
        for ( i=0; i<N; ++i ) {
            if ( players[i].isOut )
                continue;
            if ( isPass(players[i].numbers[j], isGiven, passedNumbers, passedEnd) ) {
                isGiven[players[i].numbers[j]] = 1;
                passedNumbers[passedEnd++] = players[i].numbers[j];
            } else {
                players[i].isOut = true;
                printf("Round #%d: %d is out.\n", j+1, i+1);
            }
        }
    }

    bool isThereWinner = false;
    for ( i=0; i<N; ++i ) {
        if ( ! isThereWinner && ! players[i].isOut ) {
            printf("Winner(s): %d", i+1);
            isThereWinner = true;
        } else if ( ! players[i].isOut ) {
            printf(" %d", i+1);
        }
    }
    if ( ! isThereWinner )
        printf("No winner.\n");

    return EXIT_SUCCESS;
}

改进:

把用新的算法改进了isPass函数,减少了一层循环会比原来快许多,另外宏MAXA需要增大一倍防止越界,其他不变

#define MAXA 200008

bool isPass(int num, int isGiven[], int passedNumbers[], int passedEnd) {
    int i;

    if ( isGiven[num] )
        return false;
    for ( i=0; i<passedEnd; ++i ) {
        if ( num < passedNumbers[i] && isGiven[passedNumbers[i] - num] )
            return true;
        else if ( num > passedNumbers[i] && isGiven[passedNumbers[i] + num] )
            return true;
    }

    return false;
}

猜你喜欢

转载自blog.csdn.net/herbertyellow/article/details/129090964