本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题目链接:
ac.nowcoder.com/acm/contest…
红与紫两人玩游戏,游戏如下:
一个包含小写字母的字符串,红在一个空字符串末尾添加一个字母,要求形成的新字符串为给出字符串的子序列,然后紫选一个字母在该新字符串末尾添加,两个人轮流,直到不能操作则输。
两个人轮流玩游戏一般就是博弈论的题目。
博弈论就要想到sg函数,就要想到要讨论必胜与必败的情况。
必胜必败一般从后面开始倒推。
那么本题:
假设一个字符串:bcabcdebceac
选中最后一个字母必然是必胜状态(用[]表示):bcabcdecea[c]
那么到前面最近的相同字母的区间为必败状态(用()表示):bcabcde(cea)[c]
然后必败状态前面的字母必然为必胜状态:bcabcde[b](cea)[c]
依次类推::bc[a](bcde)[b](cea)[c],因为前面的[a]必胜区间没有相同的a与其对应,注意bc不考虑作为必败区间
可以发现只要先手选择必胜区间,那么后手的选择一定在必败区间。
如何判断胜负:
只要看能形成区间的第一个字母在什么区间,如果在必胜区间,那么红胜;若在必败区间,则紫胜。
代码:
j代表必胜区间的下标
i是遍历必败区间的下标,当访问到有字母等于必胜区间的字母,j就开始变为i-1(前一个必胜区间的下标)
这个是主要对sg函数有一定的了解,能够通过必胜态和必败态推导出他们之间的相对关系。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
int main()
{
string s;
cin>>s;
int j = s.size()-1;
for(int i=j-1;i>=0;i--)
{
if(s[j] == s[i])
{
j = i - 1;
i = j;
}
}
if(j == -1) cout<<"yukari\n";
else cout<<"kou\n";
return 0;
}