CCF_201803_4_棋局评估_极大极小搜索法

极小极大搜索方法

五子棋看起来有各种各样的走法,而实际上把每一步的走法展开,就是一颗巨大的博弈树。在这个树中,从根节点为0开始,奇数层表示电脑可能的走法,偶数层表示玩家可能的走法。

假设电脑先手,那么第一层就是电脑的所有可能的走法,第二层就是玩家的所有可能走法,以此类推。

我们假设平均每一步有50种可能的走法,那么从根节点开始,往下面每一层的节点数量是上一层的 50被,假设我们进行4层思考,也就是电脑和玩家各走两步,那么这颗博弈树的最后一层的节点数为 50^4 = 625W 个。

先不考虑这么多个节点需要多久能算出来。有了对博弈树的基本认识,我们就可以用递归来遍历这一棵树。

那么我们如何才能知道哪一个分支的走法是最优的,我们就需要一个评估函数能对当前整个局势作出评估,返回一个分数。我们规定对电脑越有利,分数越大,对玩家越有利,分数越小,分数的起点是0。

我们遍历这颗博弈树的时候就很明显知道该如何选择分支了:

电脑走棋的层我们称为 MAX层,这一层电脑要保证自己利益最大化,那么就需要选分最高的节点。

玩家走棋的层我们称为MIN层,这一层玩家要保证自己的利益最大化,那么就会选分最低的节点。

这也就是极大极小值搜索算法的名称由来。

一般应用在博弈搜索中,比如:围棋,五子棋,象棋等。结果有三种可能:胜利、失败和平局。暴力搜索,如果想通过暴力搜索,把最终的结果得到的话,搜索树的深度太大了,机器不能满足,一般都是规定一个搜索的深度,在这个深度范围内进行深度优先搜索。

假设:A和B对弈,轮到A走棋了,那么我们会遍历A的每一个可能走棋方法,然后对于前面A的每一个走棋方法,遍历B的每一个走棋方法,然后接着遍历A的每一个走棋方法,如此下去,直到得到确定的结果或者达到了搜索深度的限制。当达到了搜索深度限制,此时无法判断结局如何,一般都是根据当前局面的形式,给出一个得分,计算得分的方法被称为评价函数,不同游戏的评价函数差别很大,需要很好的设计。

在搜索树中,表示A走棋的节点即为极大节点,表示B走棋的节点为极小节点。

//http://118.190.20.162/view.page?gpid=T70
#include<bits/stdc++.h>
using namespace std;
int mp[3][3];


bool isv(int k)
{
    for(int i=0;i<3;i++)
    {
        if(mp[i][0]==k&&mp[i][1]==k&&mp[i][2]==k) return true;
        if(mp[0][i]==k&&mp[1][i]==k&&mp[2][i]==k) return true;
    }
    if(mp[0][0]==k&&mp[1][1]==k&&mp[2][2]==k) return true;
    if(mp[0][2]==k&&mp[1][1]==k&&mp[2][0]==k) return true;
    return false;
}

int dfs(int k) //轮到k下棋
{
    int t=0;
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
          if(mp[i][j]==0) t++;
    if(k==1&&isv(2)) return -t-1;
    if(k==2&&isv(1)) return t+1;
    if(t==0) return 0;
    int mn=0x3f3f3f3f,mx=-0x3f3f3f3f;
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
    {
        if(mp[i][j]==0)
        {
            mp[i][j]=k;
            if(k==1) mx=max(mx,dfs(2));
            if(k==2) mn=min(mn,dfs(1));
            mp[i][j]=0;
        }
    }
    if(k==1) return mx;
    if(k==2) return mn;
}

int main()
{
    int T;
    cin>>T;
    while(T--)
   {
       for(int i=0;i<3;i++)
         for(int j=0;j<3;j++)
           cin>>mp[i][j];
       cout<<dfs(1)<<endl;
   }
   return 0;
}
全部评论

相关推荐

秋招进行到现在终于能写总结了。完全没想到战线会拉这么长,过程会如此狼狈,不过更应该怪自己太菜了。好在所有的运气都用在了最后,也是有个去处。背景:双2本硕科班,无竞赛,本科一段研究所实习,硕士一段大厂暑期实习但无转正。技术栈是C++&nbsp;&amp;&nbsp;Golang,实习是客户端音视频(而且是鸿蒙端开发),简历两个C++项目一个Golang项目。主要投递岗位:后端,cpp软开,游戏服务端,测开,以及一些不拘泥于Java的岗位。从8月起总共投递123家公司,笔试数不清了,约面大约30家。offer/oc/意向:友塔游戏(第一个offer,面试体验很好,就是给钱好少南瑞继保(计算机科班点击就送(限男生),不...
乡土丁真真:佬很厉害,羡慕~虽然我还没有到校招的时候,也想讲一下自己的看法:我觉得不是CPP的问题,佬的背书双2,技术栈加了GO,有两段实习。投了123,面了30.拿到11个offer。这个数据已经很耀眼了。这不也是CPP带来的吗?当然也不止是CPP。至少来说在这个方向努力过的也会有好的结果和选择。同等学历和项目选java就会有更好的吗?我个人持疑问态度。当然CPP在方向选择上确实让人头大,但是我觉得能上岸,至于最后做什么方向,在我看来并不重要。至于CPP特殊,有岗位方向的随机性,java不是不挑方向,只是没得选而已。也希望自己以后校招的时候能offer满满
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务