题目描述
石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头。如果两个人出拳一 样,则不分胜 负。在《生活大爆炸》第二季第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
输出 1
6 2
输入 2
9 5 5
0 1 2 3 4
1 0 3 2 4
输出 2
4 4
说明/提示
对于100%的数据,0<N≤200,0<NA≤200,0<NB≤200。
题解
思路1
这题本身非常简单,只需要把剪刀、石头、布、蜥蜴人、斯波克之间的关系搞清,简单模拟一下即可,于是写出了下面的憨批代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| #include<iostream> using namespace std; void judge(int &sa,int &sb,int a,int b) { if(a==0) { if(b==1) sb++; else if(b==2) sa++; else if(b==3) sa++; else if(b==4) sb++; } else if(a==1) { if(b==0) sa++; else if(b==2) sb++; else if(b==3) sa++; else if(b==4) sb++; } else if(a==2) { if(b==0) sb++; else if(b==1) sa++; else if(b==3) sb++; else if(b==4) sa++; } else if(a==3) { if(b==0) sb++; else if(b==1) sb++; else if(b==2) sa++; else if(b==4) sa++; } else if(a==4) { if(b==0) sa++; else if(b==1) sa++; else if(b==2) sb++; else if(b==3) sb++; } } void solve() { int sa=0,sb=0; int n,na,nb; int i; int ca[203],cb[203]; cin>>n>>na>>nb; for(i=1;i<=na;i++) cin>>ca[i]; for(i=1;i<=nb;i++) cin>>cb[i]; int k; for(k=1;k*na<=201;k++) { for(i=1;i<=na;i++) { if(i+k*na<=201) ca[i+k*na]=ca[i]; } } for(k=1;k*nb<=201;k++) { for(i=1;i<=nb;i++) { if(i+k*nb<=201) cb[i+k*nb]=cb[i]; } } for(i=1;i<=n;i++) judge(sa,sb,ca[i],cb[i]); cout<<sa<<' '<<sb; } int main() { solve(); return 0; }
|
思路2
在题解区看到了一篇思路较清奇的题解,可以学习一下。
A的得分(下方为A,有方为B) |
剪刀 |
石头 |
布 |
蜥蜴人 |
斯波克 |
剪刀 |
0 |
0 |
1 |
1 |
0 |
石头 |
1 |
0 |
0 |
1 |
0 |
布 |
0 |
1 |
0 |
0 |
1 |
蜥蜴人 |
0 |
0 |
1 |
0 |
1 |
斯波克 |
1 |
1 |
0 |
0 |
0 |
B的得分(下方为B,右方为A) |
剪刀 |
石头 |
布 |
蜥蜴人 |
斯波克 |
剪刀 |
0 |
1 |
0 |
0 |
1 |
石头 |
0 |
1 |
0 |
0 |
1 |
布 |
1 |
0 |
0 |
1 |
0 |
蜥蜴人 |
1 |
1 |
0 |
0 |
0 |
斯波克 |
0 |
0 |
1 |
1 |
0 |
显然,A出i,B出j,在上述两个5×5的方阵中Mij=!Mji(i=j)。
于是设计一个得分表,再让游戏次数对每一个周期取余即可。
代码2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include<iostream> using namespace std; void solve() { int sa=0,sb=0; int score[5][5]={0,0,1,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,1,1,0,0,0}; int n,na,nb; cin>>n>>na>>nb; const int N=202; int a[N],b[N]; int i; for(i=0;i<na;i++) cin>>a[i]; for(i=0;i<nb;i++) cin>>b[i]; for(i=0;i<n;i++) { sa+=score[a[i%na]][b[i%nb]]; sb+=score[b[i%nb]][a[i%na]]; } cout<<sa<<' '<<sb; } int main() { solve(); return 0; }
|