CCF CSP認證 201803-4 棋局評估 (dp) (100分)
阿新 • • 發佈:2020-09-08
經典的雙人非對稱博弈,記憶化搜尋即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1e5+10,inf=0x3f3f3f3f,mod=998244353; 5 unordered_map<ll,int> dp; 6 int a[4][4],p[4][4]; 7 ll enc() { 8 ll S=0; 9 for(int i=1; i<=3; ++i) 10 for(int j=1; j<=3; ++j) 11 S|=(ll)a[i][j]<<p[i][j]; 12 return S; 13 } 14 bool win(int f) { 15 for(int i=1; i<=3; ++i) { 16 if(a[i][1]==f&&a[i][2]==f&&a[i][3]==f)return 1; 17 if(a[1][i]==f&&a[2][i]==f&&a[3][i]==f)return 1; 18 } 19 if(a[1][1]==f&&a[2][2]==f&&a[3][3]==f)return 1; 20 if(a[1][3]==f&&a[2][2]==f&&a[3][1]==f)return 1; 21 return 0; 22 } 23 int cnt() { 24 int ret=0; 25 for(int i=1; i<=3; ++i) 26 for(int j=1; j<=3; ++j) 27 if(!a[i][j])ret++; 28 returnret; 29 } 30 int dfs(ll S,int f) { 31 if(dp.count(S))return dp[S]; 32 int& ret=dp[S]; 33 if(win(1))return ret=cnt()+1; 34 if(win(2))return ret=-(cnt()+1); 35 if(cnt()==0)return ret=0; 36 ret=f==1?~inf:inf; 37 for(int i=1; i<=3; ++i) 38 for(int j=1; j<=3; ++j) 39 if(!a[i][j]) { 40 a[i][j]=f; 41 if(f==1)ret=max(ret,dfs(S|(f<<p[i][j]),f^3)); 42 else if(f==2)ret=min(ret,dfs(S|(f<<p[i][j]),f^3)); 43 a[i][j]=0; 44 } 45 return ret; 46 } 47 48 int main() { 49 for(int i=1,now=0; i<=3; ++i) 50 for(int j=1; j<=3; ++j) 51 p[i][j]=now,now+=2; 52 int _; 53 for(scanf("%d",&_); _--;) { 54 for(int i=1; i<=3; ++i) 55 for(int j=1; j<=3; ++j) 56 scanf("%d",&a[i][j]); 57 printf("%d\n",dfs(enc(),cnt()&1?1:2)); 58 } 59 return 0; 60 }