PAT乙级1018

1018 锤子剪刀布 (20分)

题目地址:https://pintia.cn/problem-sets/994805260223102976/problems/994805304020025344

大家应该都会玩“锤子剪刀布”的游戏:两人同时给出手势,剪刀胜布,布胜锤子,锤子胜剪刀,相同平局。现给出两人的交锋记录,请统计双方的胜、平、负次数,并且给出双方分别出什么手势的胜算最大。

输入格式:

输入第 1 行给出正整数 N(≤100000),即双方交锋的次数。随后 N 行,每行给出一次交锋的信息,即甲、乙双方同时给出的的手势。C 代表“锤子”、J 代表“剪刀”、B 代表“布”,第 1 个字母代表甲方,第 2 个代表乙方,中间有 1 个空格。

输出格式:

输出第 1、2 行分别给出甲、乙的胜、平、负次数,数字间以 1 个空格分隔。第 3 行给出两个字母,分别代表甲、乙获胜次数最多的手势,中间有 1 个空格。如果解不唯一,则输出按字母序最小的解。后面那个输出获胜最多的手势我感觉逻辑很容易出现遗漏的情况。

输入样例

10
C J
J B
C B
B B
B C
C C
C B
J B
B C
J J

输出样例

5 3 2
2 3 5
B B

我的理解

我们那这个游戏叫做剪刀石头布,但是规则是一样的。统计的时候,统计甲乙任意一方的即可,因为其是互补关系,甲胜则意味着乙败,乙胜则意味着甲败,平局两者均相等。

  1. 仅统计甲乙方任一方的胜败次数即可,输出胜败次数时反向输出就是另一方的结果。
  2. 输出获胜最多的手势,实则也是按照多种规则嵌套排序的问题,认真思考,不要遗漏情况。

代码段

#include <iostream>
using namespace std;
// 找到获胜次数最多的手势
char findResultGesture(int winGesture[]);

int main() {
    int N = 0;
    cin >> N;
    // 甲、乙每次出的手势
    char first = ' ';
    char second = ' ';
    // 甲、乙按照B、C、J的顺序获胜的次数
    int firstWinGesture[] = {0, 0, 0};
    int secondeWinGesture[] = {0, 0, 0};
    // 甲的胜,平,负次数
    int win = 0, draw = 0, defeat = 0;
    for (int i = 0; i < N; i++) {
        cin >> first >> second;
        // 平局
        if (first == second) {
            draw++;
            // 甲胜
        } else if ((first == 'C' && second == 'J') || (first == 'J' && second == 'B') || (first == 'B' && second == 'C')) {
            win++;
            switch (first) {
                case 'B':
                    firstWinGesture[0]++;
                    break;
                case 'C':
                    firstWinGesture[1]++;
                    break;
                case 'J':
                    firstWinGesture[2]++;
                    break;
                default:
                    break;
            }
            // 乙胜
        } else {
            defeat++;
            switch (second) {
                case 'B':
                    secondeWinGesture[0]++;
                    break;
                case 'C':
                    secondeWinGesture[1]++;
                    break;
                case 'J':
                    secondeWinGesture[2]++;
                    break;
                default:
                    break;
            }
        }
    }
    cout << win << " " << draw << " " << defeat << endl;
    cout << defeat << " " << draw << " " << win << endl;
    cout << findResultGesture(firstWinGesture) << " " << findResultGesture(secondeWinGesture) << endl;
    return 0;
}

char findResultGesture(int winGesture[]) {
    int a = winGesture[0];
    int b = winGesture[1];
    int c = winGesture[2];
    // 三者均不相等
    if (a != b && b != c && a != c) {
        return a > b ? (a > c ? 'B' : 'J') : (b > c ? 'C' : 'J');
    } else {
        if (a == b && b != c) {
            return a > c ? 'B' : 'J';
        } else if ((b == c && c != a) || (a == c && c != b)) {
            return a > b ? 'B' : 'C';
        // 三者相等 a == b == c
        } else {
            return 'B';
        }
    }
}

更改过程

  1. 在找到获胜最多的手势findResultGesture函数中,遗漏了情况,在三者均不相等的else里面,if (a == b),时,有可能出现a == b == c的情况,此时里面的if(a > c)将会返回字符J,但是当a == b == c时,应该返回字符‘B‘。

    char findResultGesture(int winGesture[]) {
        int a = winGesture[0];
        int b = winGesture[1];
        int c = winGesture[2];
        // 三者均不相等
        if (a != b && b != c && a != c) {
            if (a > b) {
                if (a > c) {
                    return 'B';
                } else {
                    return 'J';
                }
            } else {
                if (b > c) {
                    return 'C';
                } else {
                    return 'J';
                }
            }
        } else {
            if (a == b) {
                if (a > c) {
                    return 'B';
                } else {
                    return 'J';
                }
            } else {
                if (a > b) {
                    return 'B';
                } else {
                    return 'C';
                }
            }
        }
    }
  2. 还有if() else这种返回值的写法,可以使用三目运算符进行简写,可能效率也会高一点吧。

相关推荐