http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=2320
problem G. OX
TimeLimit: 1000ms Memory Limit: 100000k
Description
Kim喜欢玩井字棋。但是他从来都没有赢过:)Kim非常好奇井字棋是否有一个必胜的策略。
给定一个局面,以及下一步该谁走(o或x),请判断在双方都足够聪明的情况下(双方一直采用最优策略),是否有一个人能够获胜(或者平局)。
Input
第一行一个整数T代表数据组数。
接下来T组数据,每组数据三行,每行三个字符串(o 或 x 或 .)
o表示这个位置有一个o
x表示这个位置有一个x
.表示这个位置是空的
接下来一行一个字符串(o 或 x),表示下一步该这个人走了。
Output
如果x有必胜策略,输出 “x win!”(不含引号)
如果o有必胜策略,输出 “o win!”(不含引号)
如果双方在最有策略下只能平局,输出 “tie!” (不含引号)
Sample
Input | Output |
2 . . . . o . x x . x . . . . . . . . x O | x win! tie! |
简单的博弈论问题
#include <cstdio>
#include <cstring>
using namespace std;
int dirx[4]= {0,-1,-1,-1};
int diry[4]= {-1,-1,0,1};
int g[11][11]= {{0}};
bool judwin(int x,int y)
{
int num=g[x][y];
for(int i=0; i<4; i++){
int sum=-1;
int tx1=x,tx2=x;
int ty1=y,ty2=y;
while(g[tx1][ty1]==num){
++sum;
tx1+=dirx[i];
ty1+=diry[i];
}
while(g[tx2][ty2]==num){
++sum;
tx2-=dirx[i];
ty2-=diry[i];
}
if(sum>=3)
return true;
}
return false;
}
int dfs2(int depth);
int dfs1(int depth)
{
if(depth>9)
return false;
bool fail1=true;
for(int i=1; i<=3; i++)
for(int j=1; j<=3; j++)
if(!g[i][j]){
g[i][j]=1;
if(judwin(i,j)){
g[i][j]=0;
return 1;
}
int houshou=dfs2(depth+1);
if(houshou==-1){
g[i][j]=0;
return 1;
}
if(houshou==0)
fail1=false;
g[i][j]=0;
}
if(fail1)return -1;
return false;
}
int dfs2(int depth)
{
if(depth>9)
return false;
bool fail2=true;
for(int i=1; i<=3; i++)
for(int j=1; j<=3; j++)
if(!g[i][j]){
g[i][j]=2;
if(judwin(i,j)){
g[i][j]=0;
return 1;
}
int houshou=dfs1(depth+1);
if(houshou==-1){
g[i][j]=0;
return 1;
}
if(houshou==0)
fail2=false;
g[i][j]=0;
}
if(fail2)return -1;
return false;
}
int main()
{
int t;
scanf("%d",&t);
while( t--) {
memset(g,-1,sizeof(g));
int a=0,b=0,ans=0;
char str[5];
for(int i=1; i<=3; i++){
scanf("\n%c %c %c\n",&str[0],&str[1],&str[2]);
for(int j=1; j<=3; j++){
if(str[j-1]=='.')
g[i][j]=0;
else if(str[j-1]=='x')
a++ , g[i][j]=1;
else if(str[j-1]=='o')
b++ , g[i][j]=2;
}
}
char ch[2];
scanf("%s",ch);
// 先判断给定的局面是否已经分出胜负
bool isok = 0;
for (int i = 1;i <= 3;++i){
if (isok ) break;
for (int j = 1;j <= 3;++j ){
if ( isok )break;
if( g[i][j] == 0 )continue;
if ( judwin(i,j) ){
if ( g[i][j] == 1 )
puts("x win!");
else
puts("o win!");
isok = 1;
}
}
}
//如果已经分出胜负就continue
if (isok ) continue;
if( *ch == 'x' )
ans=dfs1(a+b+1);
else
ans=dfs2(a+b+1);
if(ans==0)
printf("tie!\n");
else if(ans==1)
printf("%c win!\n",ch[0]);
else if(ans==-1)
{
if( *ch == 'o')
puts("x win!");
else
puts("o win!");
}
}
return 0;
}