题目描述:
题解思路:
首先要明白两种状态:必胜态与必败态
必胜态:当前状态为必胜态,意思就是说,你有一种走法可以将当前局面的状态转向必败态(对手所面临的状态),因为题中说明,游戏双方会按照自己的最优策略来游戏,既然有一种方法可以使得对手所面临的的状态为必败态,那么一定会这样走。
必败态:当前游戏方所面临的状态为必败态,无论怎么走棋,只能将下一个状态转化为必胜态(对手一定会胜利)。
如果在深度搜索的过程中,可以找到必败态的话,那么当前状态为必胜态
如若不能的话,当前的状态只能是必败态
题解代码:
//灭鼠先锋游戏
//首先一定要明白什么是必胜态与必败态
#include <bits/stdc++.h>
using namespace std;
map<string,bool> pp;
//判断该字符串是否只有一个
bool isone0(string s)
{
int num=0;
for(int i=0;i<s.length();++i){
if(s[i]== 'O')
num++; //只有一个棋子了,那么就是必败态
}
if(num==1)
return true;
//其他情况不做处理,因为判断不出来
// int tot = 0;
// for(auto x:s) if(x=='O') tot++;
// return tot == 1;
}
bool dfs(string s)
{
//判断出结束条件,就是只有一个空格了,一定是必败态
if(isone0(s))
// pp[s] = false;
return pp[s] = false;
//if(isone0(s)) return pp[s] = false; // 当棋盘只剩一个棋子
//判断这个状态是否已经存在
if(pp.count(s)==1) return pp[s]; //返回1表示可以找到
//开始走棋
//第一种情况,走1步棋子
for(int i=0;i<s.size();++i)
{
if(s[i]=='O'){
string temp2 = s;
temp2[i] = 'X';
if(dfs(temp2) == false) //如果可以到达必败态,那么一定是必胜态可以返回了
return pp[s] = true;
}
}
//第二种情况,走两步棋子
for(int i=0;i<s.size()-1;++i){
//等于三的情况跳过,是位于两个边界
if(s[i]=='O' && s[i+1]=='O'&& i!=3){
string tmp = s;
tmp[i] = tmp[i+1] = 'X';
if(dfs(tmp) == false) //如果可以到达必败态,那么一定是必胜态可以返回了
return pp[s] = true;
}
}
return pp[s] = false; //如果没能遇到必胜态,就是必败态
}
int main(){
string ss[4]={"XOOOOOOO","XXOOOOOO","OXOOOOOO","OXXOOOOO"}; //小蓝下完一步棋后的状态
//开始对每一种情况进行深搜
for(int i=0;i<4;++i){
string s = ss[i];
if(dfs(s) == false)
{
cout<<"V"; //返回值是bool类型的,如果为真,此状态就是必胜态
}
else {
cout<<"L";
}
}
return 0;
}
但是有一个问题就是:
为什么:if(isone0(s)) return pp[s] = false; // 当棋盘只剩一个棋子
不能替换为下面这种写法
if(isone0(s))
pp[s] = false;
return pp[s] = false;