CCF201803-4-棋局評估 (對抗搜尋)
阿新 • • 發佈:2019-01-11
思路:具體參考部落格
然後這裡因為是3*3的格子,所以情況不多,主要是用到了極小值極大值策略,如果資料再大,需要用到a-b剪枝。
具體ac程式碼:
#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
int t;
int a[5][5];
bool okrow(int f, int x) {//表示第f個人,第x行
return a[x][1] == f && a[x][2] == a[x][1] && a[x][1] == a[x][3];
}
bool okcol(int f, int x) { //表示第f個人,第x列
return a[1][x] == f && a[1][x] == a[2][x] && a[2][x] == a[3][x];
}
bool okxie(int f) {//判斷井字棋斜著能不能贏
if (a[1][1] == f && a[2][2] == a[1][1] && a[1][1] == a[3][3]) return 1;
if (a[3][1] == f && a[2][2] == a[3][1] && a[1 ][3] == a[2][2]) return 1;
return 0;
}
int check(int f) {//判斷當前棋盤分數
int ans = 1;
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
if (a[i][j] == 0) ans++;
}
}
if (f == 1) return ans;
else return -ans;
}
bool win(int f) {//判斷f能不能贏
if (okrow(f, 1) || okrow(f, 2) || okrow(f, 3)) return 1;
if (okcol(f, 1) || okcol(f, 2) || okcol(f, 3)) return 1;
if (okxie(f)) return 1;
return 0;
}
int dfs(int peo) { //1表示alice 2表示bob下棋
if (check(1) == 1) return 0;//如果沒有位置可以填了,那麼就是平局
int MAX = -INF;//初始化最大值
int MIN = INF;//初始化最小值
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
if (a[i][j]) continue;
a[i][j] = peo;//給當前位置賦值
if (win(peo)) {//如果下了這個棋子之後能贏
if (peo == 1) MAX = max(MAX, check(1));//比較
else MIN = min(MIN, check(2));
a[i][j] = 0;//回溯
continue;
}
//下了棋子之後不能贏,那麼就需要繼續遞迴
if (peo == 1) {
MAX = max(MAX, dfs(2));
} else {
MIN = min(MIN, dfs(1));
}
a[i][j] = 0;//回溯
}
}
if (peo == 1) return MAX;
else return MIN ;
}
int main() {
scanf("%d", &t);
while (t--) {
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
scanf("%d", &a[i][j]);
}
}
int x = win(1);//初始棋面Alice能贏
int y = win(2);//初始棋Bob能贏
if (x) printf("%d\n", check(1));
else if (y) printf("%d\n", check(2));
else printf("%d\n", dfs(1));
}
return 0;
}