zoukankan      html  css  js  c++  java
  • 【搜索】对抗搜索【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
    ",dfs(chess,op));
    	}
    	return 0;
    }
    

    资料

    对抗搜索

    The 14th Jilin Provincial Collegiate Programming

  • 相关阅读:
    Redis5.x五种数据类型常见命令
    Redis5.x安装以及常见数据类型
    《Redis5.x入门教程》正式推出
    PPT制作套路指南
    如何更优雅地对接第三方API
    软件开发要质量还是要效率?
    前后端分离对于开发人员的挑战
    Spring中老生常谈的FactoryBean
    消费端如何保证消息队列MQ的有序消费
    《ElasticSearch6.x实战教程》之实战ELK日志分析系统、多数据源同步
  • 原文地址:https://www.cnblogs.com/BeautifulWater/p/15099074.html
Copyright © 2011-2022 走看看