1. 程式人生 > 實用技巧 >CCF CSP認證 201803-4 棋局評估 (dp) (100分)

CCF CSP認證 201803-4 棋局評估 (dp) (100分)

經典的雙人非對稱博弈,記憶化搜尋即可

 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 return
ret; 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 }