P1328 [NOIP 2014 提高组] 生活大爆炸版石头剪刀布

题目背景

NOIP2014 提高组 D1T1

题目描述

石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头。如果两个人出拳一样,则不分胜负。在《生活大爆炸》第二季第 8 集中出现了一种石头剪刀布的升级版游戏。

升级版游戏在传统的石头剪刀布游戏的基础上,增加了两个新手势:

斯波克:《星际迷航》主角之一。

蜥蜴人:《星际迷航》中的反面角色。

这五种手势的胜负关系如表一所示,表中列出的是甲对乙的游戏结果。

P1328 [NOIP 2014 提高组] 生活大爆炸版石头剪刀布_第1张图片

现在,小 A 和小 B 尝试玩这种升级版的猜拳游戏。已知他们的出拳都是有周期性规律的,但周期长度不一定相等。例如:如果小 A 以 石头-布-石头-剪刀-蜥蜴人-斯波克 长度为 6 6 6 的周期出拳,那么他的出拳序列就是 石头-布-石头-剪刀-蜥蜴人-斯波克-石头-布-石头-剪刀-蜥蜴人-斯波克-...,而如果小 B 以 剪刀-石头-布-斯波克-蜥蜴人 长度为 5 5 5 的周期出拳,那么他出拳的序列就是 剪刀-石头-布-斯波克-蜥蜴人-剪刀-石头-布-斯波克-蜥蜴人-...

已知小 A 和小 B 一共进行 N N N 次猜拳。每一次赢的人得 1 1 1 分,输的得 0 0 0 分;平局两人都得 0 0 0 分。现请你统计 N N N 次猜拳结束之后两人的得分。

输入格式

第一行包含三个整数: N , N A , N B N,N_A,N_B N,NA,NB,分别表示共进行 N N N 次猜拳、小 A 出拳的周期长度,小 B 出拳的周期长度。数与数之间以一个空格分隔。

第二行包含 N A N_A NA 个整数,表示小 A 出拳的规律,第三行包含 N B N_B NB 个整数,表示小 B 出拳的规律。其中, 0 0 0 表示 剪刀 1 1 1 表示 石头 2 2 2 表示 3 3 3 表示 蜥蜴人 4 4 4 表示 斯波克。数与数之间以一个空格分隔。

输出格式

输出一行,包含两个整数,以一个空格分隔,分别表示小 A、小 B 的得分。

输入输出样例 #1

输入 #1

10 5 6
0 1 2 3 4
0 3 4 2 1 0

输出 #1

6 2

输入输出样例 #2

输入 #2

9 5 5
0 1 2 3 4
1 0 3 2 4

输出 #2

4 4

说明/提示

对于 100 % 100\% 100% 的数据, 0 < N ≤ 200 , 0 < N A ≤ 200 , 0 < N B ≤ 200 0 < N \leq 200, 0 < N_A \leq 200, 0 < N_B \leq 200 0<N200,0<NA200,0<NB200

知识点:模拟

解题思路:

1.理解游戏规则,还是石头剪刀布,不过增加了两种,那么我们根据图来画出对应关系(箭头指向代表克制,被指则为被克制)
P1328 [NOIP 2014 提高组] 生活大爆炸版石头剪刀布_第2张图片
2.生成完整出拳序列,鉴于小 A 和小 B 的出拳具有周期性,需依据周期长度生成 N 次猜拳的完整出拳序列。
例如题目中的第一个样例:10次猜拳的排列就是下图所示
P1328 [NOIP 2014 提高组] 生活大爆炸版石头剪刀布_第3张图片

3.上代码,接下来,我们就直接暴力模拟就行了

代码:

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        
        // 读取输入参数
        int N = scan.nextInt();          // 总共进行的猜拳轮数
        int N1 = scan.nextInt();         // 玩家A的出拳周期长度
        int N2 = scan.nextInt();         // 玩家B的出拳周期长度
        
        int[] A = new int[N1];           // 存储玩家A的出拳规律
        int[] B = new int[N2];           // 存储玩家B的出拳规律
        int numberA = 0, numberB = 0;    // 初始化双方得分
        
        // 读取玩家A和B的出拳序列
        for (int i = 0; i < A.length; i++) {
            A[i] = scan.nextInt();
        }
        for (int i = 0; i < B.length; i++) {
            B[i] = scan.nextInt();
        }

        // 生成每一轮的出拳序列(周期性重复)
        int[] A1 = new int[N];   // 存储玩家A的完整出拳序列(共N轮)
        int[] B1 = new int[N];   // 存储玩家B的完整出拳序列(共N轮)
        
        // 生成玩家A的出拳序列
        int j = 0;               // 当前周期位置索引
        for (int i = 0; i < A1.length; i++) {
            A1[i] = A[j];        // 取当前周期位置的出拳
            j++;                 // 移动到下一个位置
            // 当索引超过周期长度时重置为0
            if (j > A.length - 1) {
                j = 0;
            }
        }

        // 生成玩家B的出拳序列
        j = 0;
        for (int i = 0; i < B1.length; i++) {
            B1[i] = B[j];
            j++;
            if (j > B.length - 1) {
                j = 0;
            }
        }

        // 计算每一轮的胜负
        for (int i = 0; i < N; i++) {
            int a = A1[i];       // 玩家A当前轮的出拳
            int b = B1[i];       // 玩家B当前轮的出拳
            
            // 平局情况直接跳过
            if (a == b) {
                continue;
            }

            // 根据规则判断胜负
            // 玩家A出0(剪刀)
            if (a == 0) {
                if (b == 2 || b == 3) {  // 剪刀胜过布(2)和蜥蜴人(3)
                    numberA++;
                } else {                 // 否则输
                    numberB++;
                }
                continue;
            }

            // 玩家A出1(石头)
            if (a == 1) {
                if (b == 0 || b == 3) {  // 石头胜过剪刀(0)和蜥蜴人(3)
                    numberA++;
                } else {
                    numberB++;
                }
                continue;
            }

            // 玩家A出2(布)
            if (a == 2) {
                if (b == 1 || b == 4) {  // 布胜过石头(1)和斯波克(4)
                    numberA++;
                } else {
                    numberB++;
                }
                continue;
            }

            // 玩家A出3(蜥蜴人)
            if (a == 3) {
                if (b == 2 || b == 4) {  // 蜥蜴人胜过布(2)和斯波克(4)
                    numberA++;
                } else {
                    numberB++;
                }
                continue;
            }

            // 玩家A出4(斯波克)
            if (a == 4) {
                if (b == 0 || b == 1) {  // 斯波克胜过剪刀(0)和石头(1)
                    numberA++;
                } else {
                    numberB++;
                }
                continue;
            }
        }

        // 输出结果
        System.out.println(numberA + " " + numberB);
    }
}

你可能感兴趣的:(算法,算法)