对抗搜索
轮流搜索
- 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\n",dfs(chess,op));
}
return 0;
}
资料
The 14th Jilin Provincial Collegiate Programming