本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
【CCPC】绵阳站 M. Rock-Paper-Scissors Pyramid | 栈
题目链接
题目
- If the two blocks immediately below a block have the same shape (namely, both are R, P, or S), we will place the same shape on the block.
- If the two blocks immediately below a block have different shapes, we will place the winning shape on the block.
Refer to the pictures in the notes section for a clearer illustration.
Bobo wants to know, following this rule, what is the shape at the top of the pyramid?
题目大意
有一个长度为 的手势序列,仅由 R
、S
和 P
构成。其中 R
表示石头;S
表示剪刀;P
表示布。
共进行 轮游戏,每轮游戏每相邻的两个手势进行游戏,胜利者留下,如果平局则留下任意一个。每轮游戏后,手势序列的长度将会减少 1。在 轮游戏结束后输出最后胜利的手势。
游戏过程类似一个金字塔形状,可以参考上图的样例解释。
思路
我们先模拟这个过程,容易发现一层一层模拟是不可做的,我们斜着模拟。
从左到右每增加一个数字,该数字就需要逐层攀爬金字塔,与斜着的金字塔右腰上的每一个手势比较。假设我们现在处理到了 ,那么我们首先要和 比较,如果胜利就向上攀爬一层,和 比较……直到爬上 金字塔的顶峰,或者在中途输掉。如果 在攀爬途中输掉,就会换成此次与 比较的那个手势取代 继续向上攀爬。
容易发现用 更新完之后 金字塔的右腰自下而上变成了:
- 连续 胜利次数个 。
- 从 第一次失败开始沿着 金字塔到顶端的所有元素。
又因为显然若干个相同手势可以压成一个手势,整个过程就可以抽象为维护一个栈:每次加入新的手势 时一直退栈直到栈顶元素将会赢过 ,然后让手势 入栈。所有元素入栈后输出栈顶元素即可。
代码
#include <stdio.h>
#include <string.h>
const int N=1000005;
char a[N];
char q[N];
int tot;
int check(char a,char b)
{
if (a=='S'&&b=='R') return 0;
if (a=='R'&&b=='P') return 0;
if (a=='P'&&b=='S') return 0;
return 1;
}
char solve()
{
scanf("%s",a+1);
int n=strlen(a+1);
tot=0;
for (int i=1;i<=n;++i)
{
while (tot!=0&&check(a[i],q[tot])) tot--;
q[++tot]=a[i];
}
return q[1];
}
int main()
{
int T;
for (scanf("%d",&T);T--;)
printf("%c\n",solve());
return 0;
}