POJ 3317 博弈-极大极小过程+记忆化搜索+剪枝

1.current player 不一定是0

2.TLE想到记忆化搜索,想到怎样记录状态,注意到空位不大于10个,从这里做文章:

在搜索过程中,每个空位有三种情况:还是空的(0),被0填充(1),被1填充(2),用个三进制数记录(now)

在搜索过程中,需要枚举还没被填充的空位,需要记录对于每个状态哪个空位还没被填充的:被填充(0),被填充(1),用二进制数记录(state)

3.alpha+beta 剪枝,在搜索某个节点的子树过程中,发现当前子树怎样也无法得到比“当前已搜索过的子树得到的结果”(alpha或者beta)更优的结果时return

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include <set>
#include <cmath>
#include <queue>
#include <string>
#include <vector>
using namespace std;
struct Point
{
	int x,y;
	Point()
	{
		Point(0,0);
	}
	Point(int _x,int _y)
	{
		x=_x;y=_y;
	}
}p[100],ansp;
#define INF 10000
char mat[8][8];
int n,dp[60000],tot,pw3[60000],vis[8][8],best;
int dir[][2]={{-1,0},{1,0},{0,-1},{0,1}};
int dfs(int r,int c,char side)
{
	if(r<0 || r>=n || c<0 || c>=n || side!=mat[r][c] || vis[r][c])
		return 0;
	int cnt=1;
	vis[r][c]=1;
	for(int k=0;k<4;++k)
	{
		int nxtr=r+dir[k][0];
		int nxtc=c+dir[k][1];
		cnt+=dfs(nxtr,nxtc,side);
	}
	return cnt;
}
int get_score(int now)
{
	memset(vis,0,sizeof(vis));
	int st=now,r,c;
	for(int pos=0;st;++pos,st/=3)
	{
		char side=st%3==1?'0':'1';
		mat[p[pos].x][p[pos].y]=side;
	}
	int m0=0,m1=0;
	for(int i=0;i<n;++i)
		for(int j=0;j<n;++j)
			if(!vis[i][j])
			{
				int tt=dfs(i,j,mat[i][j]);
				if(mat[i][j]=='0')
					m0=max(m0,tt);
				else if(mat[i][j]=='1')
					m1=max(m1,tt);
			}
	st=now;
	for(int pos=0;st;++pos,st/=3)
	{
		mat[p[pos].x][p[pos].y]='.';
	}
	return m0-m1;
}
int maxsearch(int state,int dep,int now,int alpha);
int minsearch(int state,int dep,int now,int beta);
int maxsearch(int state,int dep,int now,int alpha)
{
	if(state==0) 
		return get_score(now);
	if(dp[now]!=-INF) return dp[now];
	int ans=-INF;
	int st=state;
	while(st)
	{
		int k=st&(-st);
		int pos=log(k+0.5)/log(2.0);
		int tt=minsearch(state-k,dep+1,now+pw3[pos]*1,ans);
		ans=max(tt,ans);
		if(ans>=alpha) return ans;

		if(state==(1<<tot)-1) // 初始状态
		{
			if(ans>best)
			{
				best=ans;
				ansp=p[pos];
			}
		}
		st-=k;
	}
	return dp[now]=ans;
}
int minsearch(int state,int dep,int now,int beta)
{
	if(state==0) 
		return get_score(now);
	if(dp[now]!=-INF) return dp[now];
	int ans=INF;
	int st=state;
	while(st)
	{
		int k=st&(-st);
		int pos=log(k+0.5)/log(2.0);
		int tt=maxsearch(state-k,dep+1,now+pw3[pos]*2,ans);
		ans=min(tt,ans);
		if(ans<=beta) return ans;

		st-=k;
	}
	return dp[now]=ans;
}
int main ()
{
	pw3[0]=1;
	for(int i=1;i<=10;++i)
		pw3[i]=pw3[i-1]*3;
	while(scanf("%d",&n)!=EOF && n)
	{
		int m0=0,m1=0;
		tot=0;
		for(int i=0;i<n;++i)
		{
			scanf("%s",mat[i]);
			for(int j=0;j<n;++j)
				if(mat[i][j]=='.')
				{
					p[tot++]=Point(i,j);
				}
				else if(mat[i][j]=='0')
					m0++;
				else if(mat[i][j]=='1')
					m1++;
		}
		if(m0>m1)
		{
			for(int i=0;i<n;++i)
				for(int j=0;j<n;++j)
					if(mat[i][j]=='0')
						mat[i][j]='1';
					else if(mat[i][j]=='1')
						mat[i][j]='0';
		}
		for(int i=0;i<=pw3[tot];++i)
			dp[i]=-INF;
		best=-INF;

		maxsearch((1<<tot)-1,0,0,INF);
		printf("(%d,%d) %d\n",ansp.x,ansp.y,best);
	}
	
	return 0;
}


你可能感兴趣的:(POJ 3317 博弈-极大极小过程+记忆化搜索+剪枝)