NOIP2014 提高组 D1T1
石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头。如果两个人出拳一样,则不分胜负。在《生活大爆炸》第二季第 8 集中出现了一种石头剪刀布的升级版游戏。
升级版游戏在传统的石头剪刀布游戏的基础上,增加了两个新手势:
斯波克:《星际迷航》主角之一。
蜥蜴人:《星际迷航》中的反面角色。
这五种手势的胜负关系如表一所示,表中列出的是甲对乙的游戏结果。
现在,小 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 的得分。
10 5 6
0 1 2 3 4
0 3 4 2 1 0
6 2
9 5 5
0 1 2 3 4
1 0 3 2 4
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<N≤200,0<NA≤200,0<NB≤200 。
1.理解游戏规则,还是石头剪刀布,不过增加了两种,那么我们根据图来画出对应关系(箭头指向代表克制,被指则为被克制)
2.生成完整出拳序列,鉴于小 A 和小 B 的出拳具有周期性,需依据周期长度生成 N 次猜拳的完整出拳序列。
例如题目中的第一个样例:10次猜拳的排列就是下图所示
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);
}
}