【对抗搜索】P4576 [CQOI2013]棋盘游戏
学习对抗搜索的第一篇题解记录。
对抗搜索
定义
竞争环境中多个玩家之间的目标是有冲突的,称为对抗搜索问题。
特点
-
确定的、完全可查的环境。
-
智能体轮流行动。
-
零和博弈。
-
每一步行动的结果确定。
分析
结合本题进行讲解。
分析可以发现,当一开始如果双方是相邻的,自然是先手获胜。否则,后手一定获胜,感性的理解是:后手总能将先手逼到一个角落使先手必败。
于是我们的做法是:
一开始如果双方是相邻的直接输出先手胜。
否则,先手的目标是尽量拖延自己的生存时间,后手的目标是尽快击败对手。
由上述特征,可知这是一个对抗搜索问题。
具体来讲,就是在搜索的过程中,如果轮到先手决策,那就尽可能地转移到生存时间最长的状态。而轮到后手决策时则尽可能地转移到最快击败对手的状态。
结合代码理解(很短的hh)
#include<bits/stdc++.h>
using namespace std;
// 因为 luogu 的 y1 会导致 CE,因此可以 #define 一个其他名字。
#define y1 Tenshi
const int N=21, INF=0x3f3f3f3f;
int n, x1, y1, x2, y2;
int f[2][65][N][N][N][N]; // 记录状态
// 控制四个方向
int dx[]={-1, 1, 0, 0};
int dy[]={0, 0, -1, 1};
int dfs(bool ok, int cnt, int x1, int y1, int x2, int y2){
if(~f[ok][cnt][x1][y1][x2][y2]) return f[ok][cnt][x1][y1][x2][y2];
if(cnt>3*n) return f[ok][cnt][x1][y1][x2][y2]=INF;
if(x1==x2 && y1==y2) return f[ok][cnt][x1][y1][x2][y2]=(ok? 0: INF);
int res;
if(ok){ // 先手
res=-1;
for(int i=0; i<4; i++){
int kx=x1+dx[i], ky=y1+dy[i];
if(kx<1 || kx>n || ky<1 || ky>n) continue;
res=max(res, dfs(0, cnt+1, kx, ky, x2, y2));
}
}
else{ // 后手
res=INF;
for(int i=0; i<4; i++){
for(int j=1; j<=2; j++){
int kx=x2+j*dx[i], ky=y2+j*dy[i];
if(kx<1 || kx>n || ky<1 || ky>n) continue;
res=min(res, dfs(1, cnt+1, x1, y1, kx, ky));
}
}
}
return f[ok][cnt][x1][y1][x2][y2]=res+1;
}
int main(){
memset(f, -1, sizeof f);
cin>>n>>x1>>y1>>x2>>y2;
if(abs(x1-x2)+abs(y1-y2)==1) puts("WHITE 1");
else cout<<"BLACK "<<dfs(1, 0, x1, y1, x2, y2)<<endl;
return 0;
}
分类:
算法笔记
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】