问题描述
小明常常玩 LOL 游戏上瘾,一次他想挑战K大师,不料K大师说:
“咱们先来玩个空格填字母的游戏,要是你不能赢我,就再别玩LOL了”。
K大师在纸上画了一行n个格子,要小明和他交替往其中填入字母。
而且:
1. 轮到某人填的时候,只能在某个空格中填入L或O
2. 谁先让字母组成了“LOL”的字样,谁获胜。
3. 若是全部格子都填满了,仍没法组成LOL,则平局。
小明试验了几回都输了,他很惭愧,但愿你能用计算机帮他解开这个谜。
输入格式
第一行,数字n(n<10),表示下面有n个初始局面。
接下来,n行,每行一个串,表示开始的局面。
好比:“******”, 表示有6个空格。“L****”, 表示左边是一个字母L,它的右边是4个空格。
输出格式
要求输出n个数字,表示对每一个局面,若是小明先填,当K大师老是用最强着法的时候,小明的最好结果。
1 表示能赢
-1 表示必输
0 表示能够逼平
样例输入
4
***
L**L
L**L***L
L*****L
样例输出
0
-1
1
1
//解题思路:这一题是含有平局的无偏博弈问题。博弈问题通常思路:
f( 当前局势 )
{
临界条件
t = 负
for( 全部步数 ){
t = f(尝试走一步)
if( t==负 ) return 胜
if( t==平 ) t = 平
}
return t
}
即尝试一步,改变当前局势,交给对方处理。每一方都尽量但愿胜利,其次平局。
这里直接用dfs()会超时,能够用C++ map 将一个局势 和 最终结果一一对应。 map.find()若是未找到 则 == map.end() string.find()未找到返回-1
//实现代码:
#include<iostream>
#include<string>
#include<map>
using namespace std;
//输入
int n;
string str;//当前状态
map<string,int> m;//键值对 用来把相同情况剪枝
int dfs(string str)// 返回 1 0 -1
{
if( m.find(str)!=m.end() ){
return m[str];//若是重复 剪枝
}
if( (str.find("LO*")+1)||(str.find("*OL")+1)||(str.find("L*L")+1)){
return m[str] = 1;//若是发现任意一个 则胜利(+1后返回值>=1 未找到返回0)
}
/*** 上面代码若是改成
if( str.find("LOL") ){
return m[str] = -1;//若是发现任意一个 则胜利(+1后返回值>=1 未找到返回0)
}
逻辑上也是对的 但运行会超时 大概是多了没必要要的递归 ***/
if( str.find('*')==-1 ){
return m[str] = 0;//没有空位* 则平局
}
int flat = -1;
for(int i=0; i<str.length(); i++)
{
if( str[i] != '*' )
{
continue;
}
//尝试两种方式
str[i] = 'L';
if( dfs(str)==-1 ){
str[i] = '*';//这里要先回溯为传入时的状态 再存入map
return m[str] = 1;
}
if( dfs(str)==0 ){
flat = 0;
}
str[i] = 'O';
if( dfs(str)==-1 ){
str[i] = '*';
return m[str] = 1;
}
if( dfs(str)==0 ){
flat = 0;
}
str[i] = '*';//回溯
}
return m[str] = flat;
}
void solve()
{
int res = dfs(str);
cout<<res<<endl;
}
int main()
{
cin>>n;
while( n-- )
{
cin>>str;
solve();
}
return 0;
}