题目链接:点击打开链接
此人输了的条件是无论怎么走:对方都赢了
此人获胜的条件是有至少一种方式可以获胜,那么能获胜
此人平手的条件是至少有一种方式平手
状态压缩+记忆化深搜
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#define Alice 0
#define Bob 1
#define Win 0
#define Lose 1
#define Draw 2
using namespace std;
const int N=10;
const int repeat=3;
const int SIZE=4;
const int MAXN=45000000;
int dp[MAXN];
const char color[]= {'X','O'};
char chess[N][N];
//相对于下面的isVic()来说,这个判断相对过慢
/*inline bool check(int x,int y,int dx,int dy,char sn)
{
for(int i=0;i<repeat;i++)
{
int cx=x+i*dx;
int cy=y+i*dy;
if(cx<0||cy<0||cx>=SIZE||cy>=SIZE) return false;
if(chess[cx][cy]!=sn) return false;
}
return true;
}
inline bool isVic(char sn)
{
for(int i=0;i<SIZE;i++)
for(int j=0;j<SIZE;j++)
if(chess[i][j]==sn)
{
if(check(i,j,1,1,sn)) return true;
if(check(i,j,1,0,sn)) return true;
if(check(i,j,0,1,sn)) return true;
if(check(i,j,1,-1,sn)) return true;
}
return false;
}*/
int isVic(char ch)
{
int i,j;
for(i=0; i<=1; i++)
for(j=0; j<=1; j++)
{
if ( ch == chess[i][j] )
{
if ( ch == chess[i][j+1] && ch == chess[i][j+2] )
return true;
if ( ch == chess[i+1][j+1] && ch == chess[i+2][j+2] )
return true;
if ( ch == chess[i+1][j] && ch == chess[i+2][j] )
return true;
}
}
for(i=0; i<=1; i++)
for(j=2; j<=3; j++)
if ( ch == chess[i][j] )
{
if ( ch == chess[i+1][j] && ch == chess[i+2][j] )
return true;
if ( ch == chess[i+1][j-1] && ch == chess[i+2][j-2] )
return true;
}
for(i=2; i<=3; i++)
for(j=0; j<=1; j++)
if ( ch == chess[i][j] )
if ( ch == chess[i][j+1] && ch == chess[i][j+2] )
return true;
return false;
}
const int col[]= {1,3,9,27,
81,243,729,2187,
6561,19683,59049,177147,
531441,1594323,4782969,14348907
};
inline int to_status()
{
int ret=0;
for(int i=0; i<SIZE; i++)
for(int j=0; j<SIZE; j++)
{
int sign;
int pos=i*SIZE+j;
if(chess[i][j]=='_') sign=0;
else if(chess[i][j]=='O') sign=col[pos];
else sign=col[pos]<<1;
ret+=sign;
}
return ret;
}
//返回的是该人胜负情况
//depth表示当前要下的是第depth步
int dfs(int depth,int person)
{
if(depth==17) return Draw;
int status=to_status();
if(dp[status]) return dp[status];
bool candraw=false;
for(int i=0; i<SIZE; i++)
for(int j=0; j<SIZE; j++)
if(chess[i][j]=='_')
{
//表示落子当前点
chess[i][j]=color[person];
if(isVic(color[person]))
{
chess[i][j]='_';
return dp[status]=Win;
}
int flag=dfs(depth+1,person^1);
chess[i][j]='_';
if(flag==Draw) candraw=true;
if(flag==Lose) return dp[status]=Win;
else continue;
//此人输了的条件是无论怎么走:对方都赢了
//此人获胜的条件是有一种方式可以获胜,那么能获胜
//此人平手的条件是至少有一种方式平手
}
return dp[status]=candraw?Draw:Lose;
}
int main()
{
while(scanf("%s",chess[0])!=EOF)
{
for(int i=1; i<SIZE; i++)
scanf("%s",chess[i]);
int a=0,b=0;
for(int i=0; i<SIZE; i++)
for(int j=0; j<SIZE; j++)
if(chess[i][j]=='X') a++;
else if(chess[i][j]=='O') b++;
int sign;
if(a==b) sign=dfs(a+b+1,Alice);
else sign=dfs(a+b+1,Bob);
if(sign==Win) puts("Win");
else if(sign==Lose) puts("Lose");
else puts("Draw");
}
return 0;
}