- 最优策略(难点):对于alice而言,他下棋的最优策略是让棋盘最后下完得分的值越高越好,反之,bob的最优策略就是让得分越低越好。
- 尝试所有空位置,回溯求解。
代码如下
#include<iostream>
#include<cmath>
#include<climits>
using namespace std;
int a[3][3];
bool isWin(int k){
for(int i = 0; i < 3; i++){
if(a[i][0]==k&&a[i][1]==k&&a[i][2]==k) return true;
if(a[0][i]==k&&a[1][i]==k&&a[2][i]==k) return true;
}
if(a[0][0]==k&&a[1][1]==k&&a[2][2]==k) return true;
if(a[2][0]==k&&a[1][1]==k&&a[0][2]==k) return true;
return false;
}
int dfs(int k){
int t = 0;
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
if(a[i][j]==0) t++;
}
}
//递归出口
if(k==1&&isWin(2)) return -(t+1);
if(k==2&&isWin(1)) return (t+1);
if(t==0) return 0;
int maxx = -INT_MAX,minn=INT_MAX;
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
if(a[i][j]==0){
a[i][j] = k;//尝试下棋
if(k==1) maxx = max(maxx,dfs(2));
if(k==2) minn = min(minn, dfs(1));
a[i][j] = 0;
}
}
}
//所有空格都模拟完后
if(k==1) return maxx;
if(k==2) return minn;
}
int main()
{
int n,ans;
scanf("%d", &n);
for(int num = 0; num < n; num++){
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
scanf("%d", &a[i][j]);
}
}
ans = dfs(1);//Alice先下棋
cout<<ans<<endl;
}
return 0;
}