转载请注明出处,谢谢http://blog.csdn.net/acm_cxlove/article/details/7854526 by---cxlove
题目:给出一个4*4的格子,一盘棋已经进行了部分,接下来是先手下,如果出现了连续4个同样的,就算胜。问先手有没有必胜策略
http://poj.org/problem?id=1568
还是极大极小搜索,和之前的差不多
枚举起点,然后开始搜索
这里有一个强效剪枝,如果当前只下了4个或者4个以内的棋子,则必定没有必胜策略,直接从2S+到0ms
极大极小搜索策略一般都是使用在一些博弈类的游戏之中:
这样策略本质上使用的是深度搜索策略,所以一般可以使用递归的方法来实现。在搜索过程中,对本方有利的搜索点上应该取极大值,而对本方不利的搜索点上应该取极小值。
极小值和极大值都是相对而言的。
在搜索过程中需要合理的控制搜索深度,搜索的深度越深,效率越低,但是一般来说,走法越好。
极大极小搜索可以分开写,也可以放在一起写。
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<algorithm>
#include<set>
#define inf 1<<30
#define N 50005
#define maxn 100005
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define pb(a) push_back(a)
#define mem(a,b) memset(a,b,sizeof(a))
#define eps 1e-9
#define zero(a) fabs(a)<eps
#define LL long long
#define ULL unsigned long long
#define lson (step<<1)
#define rson (step<<1|1)
#define MOD 1000000007
#define mp(a,b) make_pair(a,b)
using namespace std;
char str[5][5];
int X,Y,chess;
//判断一个局面是否结束
bool check(int x,int y){
int tot=0;
//横向判断
for(int i=0;i<4;i++)
if(str[x][i]=='o') tot++;
else if(str[x][i]=='x') tot--;
if(tot==4||tot==-4) return true;
tot=0;
//纵向判断
for(int i=0;i<4;i++)
if(str[i][y]=='o') tot++;
else if(str[i][y]=='x') tot--;
if(tot==4||tot==-4) return true;
tot=0;
//正对角线判断
for(int i=0;i<4;i++)
if(str[i][i]=='o') tot++;
else if(str[i][i]=='x') tot--;
if(tot==4||tot==-4) return true;
tot=0;
//反对角线判断
for(int i=0;i<4;i++)
if(str[i][3-i]=='o') tot++;
else if(str[i][3-i]=='x') tot--;
if(tot==4||tot==-4) return true;
return false;
}
int MinSearch(int x,int y,int beta);
int MaxSearch(int x,int y,int alpha);
int MaxSearch(int x,int y,int alpha){
int ans=-inf;
//已经结束
if(check(x,y)) return ans;
//平局
if(chess==16) return 0;
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
if(str[i][j]=='.'){
str[i][j]='x';chess++;
int tmp=MinSearch(i,j,ans);
str[i][j]='.';chess--;
ans=max(ans,tmp);
//对方需要找的最差估价,如果当前比之前最差的高,剪枝
if(ans>=alpha) return ans;
}
return ans;
}
int MinSearch(int x,int y,int beta){
int ans=inf;
//已经结束
if(check(x,y)) return ans;
//平局
if(chess==16) return 0;
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
if(str[i][j]=='.'){
str[i][j]='o';chess++;
int tmp=MaxSearch(i,j,ans);
str[i][j]='.';chess--;
ans=min(ans,tmp);
//自己需要找的最高估价,如果当前比之前最差的低,剪枝
if(ans<=beta) return ans;
}
return ans;
}
bool slove(){
int beta=-inf;
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
//枚举,然后搜索
if(str[i][j]=='.'){
str[i][j]='x';chess++;
int tmp=MinSearch(i,j,beta);
str[i][j]='.';chess--;
beta=max(tmp,beta);
if(beta==inf){
X=i;
Y=j;
return true;
}
}
return false;
}
int main(){
char ch[5];
while(scanf("%s",ch)!=EOF&&ch[0]!='$'){
chess=0;
for(int i=0;i<4;i++){
scanf("%s",str[i]);
for(int j=0;j<4;j++)
chess+=str[i][j]!='.';
}
//这一步直接从2S+到0ms,哭~~~
if(chess<=4){
printf("#####\n");
continue;
}
if(slove()) printf("(%d,%d)\n",X,Y);
else printf("#####\n");
}
return 0;
}