POJ 1568 Find the Winning Move(极小极大搜索+alpha-beta剪枝)

转载请注明出处,谢谢http://blog.csdn.net/acm_cxlove/article/details/7854526       by---cxlove 

题目:给出一个4*4的格子,一盘棋已经进行了部分,接下来是先手下,如果出现了连续4个同样的,就算胜。问先手有没有必胜策略

http://poj.org/problem?id=1568 

还是极大极小搜索,和之前的差不多

枚举起点,然后开始搜索

这里有一个强效剪枝,如果当前只下了4个或者4个以内的棋子,则必定没有必胜策略,直接从2S+到0ms

参考http://blog.csdn.net/qiqijianglu/article/details/7990650

极大极小搜索策略一般都是使用在一些博弈类的游戏之中:

这样策略本质上使用的是深度搜索策略,所以一般可以使用递归的方法来实现。在搜索过程中,对本方有利的搜索点上应该取极大值,而对本方不利的搜索点上应该取极小值。

极小值和极大值都是相对而言的。

在搜索过程中需要合理的控制搜索深度,搜索的深度越深,效率越低,但是一般来说,走法越好。

极大极小搜索可以分开写,也可以放在一起写。

#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;
}


你可能感兴趣的:(游戏,pair)