题目相关
题目链接
洛谷,https://www.luogu.com.cn/problem/P1328。
我的 OJ,http://47.110.135.197/problem.php?id=4681。
题目描述
石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头。如果两个人出拳一 样,则不分胜负。在《生活大爆炸》第二季第8集中出现了一种石头剪刀布的升级版游戏。
升级版游戏在传统的石头剪刀布游戏的基础上,增加了两个新手势:
斯波克:《星际迷航》主角之一。
蜥蜴人:《星际迷航》中的反面角色。
这五种手势的胜负关系如表一所示,表中列出的是甲对乙的游戏结果。
现在,小 A
和小 B
尝试玩这种升级版的猜拳游戏。已知他们的出拳都是有周期性规律的,但周期长度不一定相等。例如:如果小A
以“石头-布-石头-剪刀-蜥蜴人-斯波克”长度为 6 的周期出拳,那么他的出拳序列就是“石头-布-石头-剪刀-蜥蜴人-斯波克-石头-布-石头-剪刀-蜥蜴人-斯波克-......”,而如果小B
以“剪刀-石头-布-斯波克-蜥蜴人”长度为 5 的周期出拳,那么他出拳的序列就是“剪刀-石头-布-斯波克-蜥蜴人-剪刀-石头-布-斯波克-蜥蜴人-......”
已知小 A
和小 B
一共进行 N 次猜拳。每一次赢的人得 1 分,输的得 0 分;平局两人都得 0 分。现请你统计 N 次猜拳结束之后两人的得分。
输入格式
第一行包含三个整数:N,NA,NB,分别表示共进行 N 次猜拳、小 A
出拳的周期长度,小 B
出拳的周期长度。数与数之间以一个空格分隔。
第二行包含 NA 个整数,表示小 A
出拳的规律,第三行包含 NB 个整数,表示小 B
出拳的规律。其中,0 表示“剪刀”,1 表示“石头”,2 表示“布”,3 表示“蜥蜴人”,4表示“斯波克”。数与数之间以一个空格分隔。
输出格式
输出一行,包含两个整数,以一个空格分隔,分别表示小 A
、小 B
的得分。
输入样例
样例 1
10 5 6
0 1 2 3 4
0 3 4 2 1 0
样例 2
9 5 5
0 1 2 3 4
1 0 3 2 4
输出样例
样例 1
6 2
样例 2
4 4
数据规模
对于100%的数据,0 < N ≤ 200, 0 < NA ≤ 200, 0 < NB ≤ 200 。
题解报告
题意分析
本题属于计算算法的模拟算法,就是用计算机来模拟题目中要求的操作。没有很大难度。
唯一要注意的地方就是胜负表怎么看。我比较笨,我就写出了这样的规则:
1、剪刀 vs 石头。剪刀输,石头赢。
2、剪刀 vs 布。剪刀赢,布输。
3、剪刀 vs 蜥蜴人。剪刀赢,蜥蜴人输。
4、剪刀 vs 斯波克。剪刀输,斯波克赢。
5、石头 vs 布。石头输,布赢。
6、石头 vs 蜥蜴人。石头赢,蜥蜴人输。
7、石头 vs 斯波克。石头输,斯波克赢。
8、布 vs 蜥蜴人。布输,蜥蜴人赢。
9、布 vs 斯波克。布赢,斯波克输。
10、蜥蜴人 vs 斯波克。蜥蜴人赢,斯波克输。
样例数据分析
样例数据 1
根据样例数据 1,一共进行了 10 轮,A 的周期为 5,B 的周期为 6。A 出拳的次序为 0 1 2 3 4,B 出拳的次序为 0 3 4 2 1 0。
由于 A 和 B 的周期不保证一样,我们需要用两个变量分别控制 A 和 B。再使用两个变量表示 A 和 B 的最终得分。这样,我们可以写出如下的 10 轮表格。
轮数 | idxA | a[idxA] | A出拳 | idxB | b[idxB] | B出拳 | 结果 | ansA | ansB |
初始 | 0 | 0 | 0 | 0 | |||||
1 | 0 | 0 | 剪刀 | 0 | 0 | 剪刀 | 平局 | 0 | 0 |
2 | 1 | 1 | 石头 | 1 | 3 | 蜥蜴人 | 石头赢 | 1 | 0 |
3 | 2 | 2 | 布 | 2 | 4 | 斯波克 | 布赢 | 2 | 0 |
4 | 3 | 3 | 蜥蜴人 | 3 | 2 | 布 | 蜥蜴人赢 | 3 | 0 |
5 | 4 | 4 | 斯波克 | 4 | 1 | 石头 | 斯波克赢 | 4 | 0 |
6 | 0 | 0 | 剪刀 | 5 | 0 | 剪刀 | 平局 | 4 | 0 |
7 | 1 | 1 | 石头 | 0 | 0 | 剪刀 | 石头赢 | 5 | 0 |
8 | 2 | 2 | 布 | 1 | 3 | 蜥蜴人 | 蜥蜴人赢 | 5 | 1 |
9 | 3 | 3 | 蜥蜴人 | 2 | 4 | 斯波克 | 蜥蜴人赢 | 6 | 1 |
10 | 4 | 4 | 斯波克 | 3 | 2 | 布 | 布赢 | 6 | 2 |
这样,我们可以得到最终比分为 6:2。
数据规模分析
0 < N ≤ 200。非常简单的一个问题。
难点
个人觉得本题的难点有以下几个。
1、如何判断输赢。我比较笨,用了最笨的枚举所有组合情况,实在想不出有什么简单的判断方法。
2、如何控制 A 和 B 的周期。
AC 参考代码
//https://www.luogu.com.cn/problem/P1328
#include <iostream>
using namespace std;
const int MAXN = 2e2+4;
int a[MAXN];
int b[MAXN];
int main() {
int n, na, nb;
cin>>n>>na>>nb;
for (int i=0; i<na; i++) {
cin>>a[i];
}
for (int i=0; i<nb; i++) {
cin>>b[i];
}
int ansa=0;
int ansb=0;
int idxa=0;
int idxb=0;
for (int i=0; i<n; i++) {
if (0==a[idxa]) {
//a 剪刀
if (0==b[idxb]) {
//剪刀 vs 剪刀
} else if (1==b[idxb]) {
//剪刀 vs 石头
//剪刀 lose
ansb++;
} else if (2==b[idxb]) {
//剪刀 vs 布
//剪刀 win
ansa++;
} else if (3==b[idxb]) {
//剪刀 vs 蜥蜴人
//剪刀 win
ansa++;
} else {
//剪刀 vs 斯波克
//剪刀 lose
ansb++;
}
} else if (1==a[idxa]) {
//a 石头
if (0==b[idxb]) {
//石头 vs 剪刀
//石头 win
ansa++;
} else if (1==b[idxb]) {
//石头 vs 石头
} else if (2==b[idxb]) {
//石头 vs 布
//石头 lose
ansb++;
} else if (3==b[idxb]) {
//石头 vs 蜥蜴人
//石头 win
ansa++;
} else {
//石头 vs 斯波克
//石头 lose
ansb++;
}
} else if (2==a[idxa]) {
//a 布
if (0==b[idxb]) {
//布 vs 剪刀
//布 lose
ansb++;
} else if (1==b[idxb]) {
//布 vs 石头
//布 win
ansa++;
} else if (2==b[idxb]) {
//布 vs 布
} else if (3==b[idxb]) {
//布 vs 蜥蜴人
//布 lose
ansb++;
} else {
//布 vs 斯波克
//布 win
ansa++;
}
} else if (3==a[idxa]) {
//a 蜥蜴人
if (0==b[idxb]) {
//蜥蜴人 vs 剪刀
//蜥蜴人 win
ansb++;
} else if (1==b[idxb]) {
//蜥蜴人 vs 石头
//蜥蜴人 lose
ansb++;
} else if (2==b[idxb]) {
//蜥蜴人 vs 布
//蜥蜴人 win
ansa++;
} else if (3==b[idxb]) {
//蜥蜴人 vs 蜥蜴人
} else {
//蜥蜴人 vs 斯波克
//蜥蜴人 win
ansa++;
}
} else {
//a 斯波克
if (0==b[idxb]) {
//斯波克 vs 剪刀
//斯波克 win
ansa++;
} else if (1==b[idxb]) {
//斯波克 vs 石头
//斯波克 win
ansa++;
} else if (2==b[idxb]) {
//斯波克 vs 布
//斯波克 lose
ansb++;
} else if (3==b[idxb]) {
//斯波克 vs 蜥蜴人
//斯波克 lose
ansb++;
} else {
//b 斯波克
}
}
idxa=(idxa+1)%na;
idxb=(idxb+1)%nb;
}
cout<<ansa<<" "<<ansb<<"\n";
return 0;
}
算法复杂度
时间复杂度
O(N)。
空间复杂度
O(N)。