题目链接:字符串游戏
题意
现在有一个字符串s,每个人可以选择字符串中的某一个区间和一种字符,删除这个区间内的所有该字符(需要删除字符的数量至少为1)。从Alice开始,Alice与Bob轮流进行进行这个操作,若在某个玩家删除前,字符串已经为空,则该玩家获胜。
假设Alice和Bob都会按照其最优的解法删除,Alice想知道,她是否可以获胜。
题解
我们来分析这道题,这个删除操作其实可以看作至少删除一个同种字符,最多无上限甚至可以全部删除。
现在Alice先手,最后删除完的人是输而不是赢。问谁能获胜。
看完这个题想必大家心中已经有一个模型——Nim博弈。
相同的字符可以看为一堆石子,每次我们只能从同堆中取至少一个石子,最多可以全部取完。不同的是最后取完的是输而不是赢。
通过画出状态图,我们能得出这种反Nim博弈类型的题影响的只有石子全为1的情况,剩下的是不影响的。
- 当石子全为1,很明显如果能整除2,那么先手胜;否则,后手胜。
- 当石子至少有一个不为1时,判断条件和Nim博弈相同,异或石堆,为0时后手胜;否则,先手胜。
我们从最后的状态考虑,每个石堆的状态在最后都能转化为两种情况:1.取走大于1的那一堆,其余(n-1)每堆石子全为1。2.n堆石子数全为1。
所以在状态图中,一定会有一层出现上述两种情况。
而反Nim博弈在石子全为1时的必胜态恰恰与Nim博弈相反,所以在Nim博弈的状态图中有一层出现上述两种情况时,在反Nim博弈中胜变负、负变胜,对于上一层状态,很明显是仍然不变的。所以当至少有石子不为1时,判断条件和Nim博弈相同。
代码
class Solution {
public:
/**
* @param s: a string for this game
* @return: return whether Alice can win this game
*/
map<char,int> book;
bool stringGame(string &s) {
// Write your code here.
book.clear();
int n=s.length();
for(int i=0;i<n;i++) book[s[i]]++;
int res=0,cnt=0;
for(int i=0;i<26;i++)
{
res^=book['a'+i];
if(book['a'+i]==1) cnt++;
}
if(cnt==n)
{
if(cnt%2==0) return true;
else return false;
}
else
{
if(res) return true;
else return false;
}
}
};