对抗搜索

\(minmax\) 搜索:

定义:

也叫对抗搜索,搜索时同时取最大/最小。

形式:

两人相互博弈,都希望自己的答案更优秀,即:

\(A\) 希望自己答案更大,\(B\) 希望 \(A\) 的答案更小。

解决:

在搜索时,我们进行人物的判断:

若当前是 \(A\) ,我们的转移方程中就取 \(max\)

若当前是 \(B\) , 我们的转移方程中就取 \(min\).

可能这样还不够详细,选一道例题分析一下:

[CQOI2013]棋盘游戏

这道题就是典型的对抗搜索类型的题目。

分析

平局的状态很好选择,就是走的步数过多了,我们考虑能搜索到的情况:

\(A\) 希望移动多,所以对每个方向搜索时,取能移动的最大步数,更加优秀

\(B\) 希望移动少,所以取能移动的最小部署。

因为数据范围比较小,爆搜是可以的,最后判断是否重合即可。

#include<bits/stdc++.h>
using namespace std;
int dx[8]={0,1,0,-1,0,2,0,-2};
int dy[8]={1,0,-1,0,2,0,-2,0};
int f[2][81][21][21][21][21],inf=2e9,n;
int v,X1,Y1,X2,Y2;
int dfs(int opt,int y,int X1,int Y1,int X2,int Y2){
    int res;
    if(y>3*n) return inf;//步数过多
    if(X1==X2&&Y1==Y2){
        if(opt==0) return 0;
        else return inf;
    }
    if(f[opt][y][X1][Y1][X2][Y2]) return f[opt][y][X1][Y1][X2][Y2];
    if(!opt){
        res=0;
        for(int i=0;i<4;i++){
            int xx=X1+dx[i];
            int yy=Y1+dy[i];
            if(xx>=1&&yy>=1&&xx<=n&&yy<=n)
               res=max(res,dfs(opt^1,y+1,xx,yy,X2,Y2));    
        }
    }
    else{
        res=inf;
        for(int i=0;i<8;i++){
            int xx=X2+dx[i];
            int yy=Y2+dy[i];
            if(xx>=1&&yy>=1&&xx<=n&&yy<=n)
               res=min(res,dfs(opt^1,y+1,X1,Y1,xx,yy));
        }
    }
    f[opt][y][X1][Y1][X2][Y2]=res+1;
    return res+1;
}
int main()
{   
    cin>>n>>X1>>Y1>>X2>>Y2;
    if(abs(X1-X2)+abs(Y1-Y2)<=1) printf("WHITE 1\n");
    else{
        v=dfs(0,0,X1,Y1,X2,Y2);
        if(v>inf) printf("DRAW\n");
        else printf("BLACK %d\n",v);
    }
    system("pause");
    return 0;
}

例题:

[九省联考2018]一双木棋chess

posted @ 2021-09-27 10:25  Evitagen  阅读(140)  评论(0编辑  收藏  举报