问题描述
小明经常玩 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
LL
LLL
L**L
样例输出
0
-1
1
1
#include <iostream>
#include <cstring>
#include <vector>
#include <set>
#include <map> //用map来保存结果
using namespace std;
struct node{
string s; //局面
int pd; //对于该局面的判断
};
//vector<node> G;
map<string,int> G;
map<string,int>::iterator it;//迭代器
// map的插入操作需要用到pair
//例如
// G.insert(pair<string,int>("abc",1));
// 查找map中是否有key的 G.count("abc");
//迭代器
string Fir; //初始局面
int k;
int n; //局面个数
string A;
int dfs() //深度优先遍历
{
if(G.count(A)!=0)
{
return G[A];
}
int flag1=0; //当前局面有必胜态
int flag2=0; //下一个局面是否有平局
int flag=0; //表面当前是否有格子可用
//cout<<A<<endl;
for(int i = 0;i<k;i++)
{
if(A[i]=='*') //表示可操作格子
{
flag=1;
A[i]='L'; //加入L
if((A[i-1]=='O'&&A[i-2]=='L')||(A[i+1]=='O'&&A[i+2]=='L'))
{
A[i]='*';
G.insert(pair<string,int>(A,1));//该局面存储为胜利
return 1;
}
int u1;
u1 = dfs();
if(u1==-1)
{
flag1 = 1 ;//当前状态存在必胜
A[i]='*';
G.insert(pair<string,int>(A,1));
return 1;
}
A[i]='O';
if((A[i+1]=='L'&&A[i-1]=='L'))
{
//状态先还原
A[i]='*';
G.insert(pair<string,int>(A,1));//该局面存储为胜利
return 1;
}
int u2; //下一局面的状态
u2 = dfs();
if(u2==-1)
{
flag1 = 1 ;//当前状态存在必胜
A[i]='*';
G.insert(pair<string,int>(A,1));
return 1;
}
else if(u1==0||u2==0)
{
flag2=1; //存在平态
}
A[i]='*'; //状态还原
}
}
if(flag1==1)
{
G.insert(pair<string,int>(A,1));
return 1; //表面当前局面有必胜态
}
else if(flag1==0&&flag2==0&&flag==1)
{
G.insert(pair<string,int>(A,-1));
return -1; //下一个局面全是必败态并且有可动棋子
}
else
{
G.insert(pair<string,int>(A,0));
return 0; //其他为平态
}
}
int main()
{
cin>>n;
while(n--)
{
G.clear(); //清空上一局游戏局面
cin>>Fir ; //记录初始局
k = Fir.size();
A = Fir; //传递
printf("%d\n",dfs());
}
return 0;
}