一个n*n(n>=2)棋盘上有黑白棋子各一枚。游戏者A和B轮流移动棋子,A先走。
A的移动规则:只能移动白棋子。可以往上下左右四个方向之一移动一格。
B的移动规则:只能移动黑棋子。可以往上下左右四个方向之一移动一格或者两格。
和通常的“吃子”规则一样,当某游戏者把自己的棋子移动到对方棋子所在的格子时,他就赢了。
两个游戏者都很聪明,当可以获胜时会尽快获胜,只能输掉的时候会尽量拖延时间。你的任务是判断谁会赢,需要多少回合。
比如n=2,白棋子在(1,1),黑棋子在(2,2),那么虽然A有两种走法,第二个回合B总能取胜。
https://www.luogu.org/problemnew/show/P4576
这题好像就是传说中的对抗搜索。
好像有点像博弈,但是这道题几乎不需要博弈。
白棋一步一格,黑棋最多一步两格,这还用比嘛,差距悬殊啊,这就意味着白棋永远吃不掉黑棋,除非!!一开始黑棋就在白棋1步之内。白棋先走直接就给吃掉了,步数为1。否则!!!只可能黑棋吃掉白棋,且一定能吃掉。
这道题的中心思想:让黑棋尽快吃掉白棋(求min),让白棋尽量苟住(求max)。
然后暴搜!!
#include
#include
#include
#include
using namespace std;
const int N=21;
const int inf=214748364;
int f[2][60][N][N][N][N];
int n,x1,y1,x2,y2;
int dfs(bool id,int step,int x1,int y1,int x2,int y2)//id==0:WHITE,id==1:BLACK
{
int ans;
if(step>3*n){
return inf;
}
if(f[id][step][x1][y1][x2][y2]){
return f[id][step][x1][y1][x2][y2];
}
if(x1==x2&&y1==y2){
if(id) return inf;
else return 0;
}
if(!id){
ans=0;
if(x1>1) ans=max(ans,dfs(1,step+1,x1-1,y1,x2,y2));
if(x11) ans=max(ans,dfs(1,step+1,x1,y1-1,x2,y2));
if(y11) ans=min(ans,dfs(0,step+1,x1,y1,x2-1,y2));
if(x22) ans=min(ans,dfs(0,step+1,x1,y1,x2-2,y2));
if(x21) ans=min(ans,dfs(0,step+1,x1,y1,x2,y2-1));
if(y22) ans=min(ans,dfs(0,step+1,x1,y1,x2,y2-2));
if(y2