Title

【搜索】对抗搜索【CF】J. Situation

对抗搜索

轮流搜索

  • op的值为0或1,通过1-op来使得op可以在0和1之间进行切换
int dfs(int op){
    if(op)
       dfs(1-op);
    else
       dfs(1-op);
    return ;
}

对抗搜索(博弈搜索)

  • 一下子要求答案朝着一个方向发展,一下子又要求答案朝着另一个方向发展。
int dfs(int op){
    if(op){
        在接下来搜索到的所有可能答案中取到最大值
    }
    else{
        在接下来搜索到的所有可能答案中取到最小值
    }
}

对抗记忆化min_max搜索模板(最大最小化搜索/博弈搜索)

int dfs(){
    if(dp!=初始值) return dp[st][op];
    if(op){//max
        dp = max(dp,dfs(1-op));
    }
    else{//min
        dp = min(dp,dfs(1-op));
    }
    return dp[st][op];
}

井字格游戏(博弈搜索Problem J. Situation

思路:将棋盘上的一种种摆放通过哈希换算成数字展示出来

井子格

  • 哈希值(进制的思想,换成数字来表示一个个对应的状态)
int get_hash()
{
     int ans = 0;
     for(int i=0;i<N;i++)
        for(int j=0;j<N;j++)
            if(g[i][j]=='.')ans += 0;
            if(g[i][j]=='X')ans += 1;
            if(g[i][j]=='O')ans += 2;
}
  • 判等

    bool r_is_same(int r)
    {
        return g[r][0] == g[r][1] && g[r][1] == g[r][2];
    }
    

    纵行

    bool c_is_same(int c)
    {
        return g[0][c] == g[1][c] && g[1][c] == g[2][c];
    }
    

    主对角线(x==y)

    bool x1_is_same()
    {
        return g[0][0] == g[1][1] && g[1][1] == g[2][2]; 
    }
    

    副对角线(x+y=N)

    bool x2_is_same()
    {
        return g[0][2] == g[1][1] && g[1][1] == g[2][0];
    }
    
  • 计算得分

    int cal()
    {
          int score1=0,score2=0;
          for(int i=0;i<3;i++)
          {
                if(r_is_same(i))
                   if(g[i][0]=='X') score1++;
                   else if(g[i][0]=='O') score2++;
                 
                if(c_is_same(i))
                   if(g[0][i]=='X') score1++;
                   else if(g[0][i]=='O') score2++;
          }
          
          if(x1_is_same())
             if(g[1][1]=='X') score1++;
             else if(g[1][1]=='O') score2++;
          
          if(x2_is_same())
             if(g[1][1]=='X') score1++;
             else if(g[1][1]=='O') score2++;
             
          return score1 - score2;     
    }
    
  • 判断是否填充完毕

    井字格内是否还存在用来表示未填入的字符

    bool is_end()
    {
        for(int i=0;i<N;i++)
           for(int j=0;j<N;j++)
               if(g[i][j]=='.')
                  return false;
        return true;        
    }
    

ac代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int N = 3;

struct Chess{
	char g[N][N];
	
	int get_hash()
	{
		int res = 0;
		for(int i=0;i<3;i++)
		    for(int j=0;j<3;j++)
		    {
		    	if(g[i][j]=='.') res=res*3+0;
				if(g[i][j]=='O') res=res*3+1;
				if(g[i][j]=='X') res=res*3+2; 
			}
	    return res;
	}
	
	bool r_is_same(int r)
	{
		return g[r][0] == g[r][1] && g[r][1] == g[r][2];
	}
	
	bool c_is_same(int c)
	{
		return g[0][c] == g[1][c] && g[1][c] == g[2][c];
	}
	
	bool x1_is_same()
	{
		return g[0][0] == g[1][1] && g[1][1] == g[2][2];
	}
	
	bool x2_is_same()
	{
		return g[2][0] == g[1][1] && g[1][1] == g[0][2];
	}
	
	int cal()
	{
		int s1=0,s2=0;
		for(int i=0;i<3;i++)
		{
			if(r_is_same(i))
			   if(g[i][0]=='O') s1++;
			   else if(g[i][0]=='X') s2++;
			   
			if(c_is_same(i))
			   if(g[0][i]=='O') s1++;
			   else if(g[0][i]=='X') s2++;
		}
		
		if(x1_is_same())
			if(g[1][1]=='O') s1++;
			else if(g[1][1]=='X') s2++;
			   
		if(x2_is_same())
			if(g[1][1]=='O') s1++;
			else if(g[1][1]=='X') s2++;
			
		return s1-s2;
	}
	
	bool is_end()
	{
		for(int i=0;i<3;i++)
		    for(int j=0;j<3;j++)
		        if(g[i][j]=='.')
		           return false;
		return true;
	}
};


int dp[100007][2];
int dfs(Chess chess,int op)
{
	int hash = chess.get_hash();
	if(dp[hash][op]!=INF) return dp[hash][op];//记忆化搜索 
	if(chess.is_end()) return chess.cal();
	if(op==1)
	{
		dp[hash][1] = -INF;
		for(int i=0;i<3;i++)
		    for(int j=0;j<3;j++)
		        if(chess.g[i][j]=='.')
		        {
		        	Chess chess2 = chess;
		        	chess2.g[i][j] = 'O';
		        	dp[hash][1] = max(dp[hash][1],dfs(chess2,1-op)); 
				}
	}
	else
	{	
	    for(int i=0;i<3;i++)
		    for(int j=0;j<3;j++)
		        if(chess.g[i][j]=='.')
		        {
		        	Chess chess2 = chess;
		        	chess2.g[i][j] = 'X';
		        	dp[hash][0] = min(dp[hash][0],dfs(chess2,1-op)); 
				}
	}
	 return dp[hash][op];
}

int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		memset(dp,0x3f,sizeof(dp));
		int op;
		scanf("%d",&op);
		Chess chess;
		for(int i=0;i<3;i++)
		        scanf("%s",chess.g[i]);
		
		printf("%d\n",dfs(chess,op));
	}
	return 0;
}

资料

对抗搜索

The 14th Jilin Provincial Collegiate Programming

posted @ 2021-08-04 15:25  BeautifulWater  阅读(161)  评论(0编辑  收藏  举报