【CCF】棋局评估

博弈论极小极大搜索,记忆化+状压

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=2e4+3;
const int inf=11;
int a[10];
int three[10];
int tmp[10];
int ans[maxn][2];
void pre(){
    three[0]=1;
    for(int i=1;i<10;i++){
        three[i]=three[i-1]*3;
    }
}
int judge(vector<int> tmp){
    int res=0;
    for(int i=0;i<9;i++){
        res+=(tmp[i]==0);
    }
    //ALice
    if(tmp[0]==1&&tmp[1]==1&&tmp[2]==1){
        return res+1;
    }
    if(tmp[3]==1&&tmp[4]==1&&tmp[5]==1){
        return res+1;
    }
    if(tmp[6]==1&&tmp[7]==1&&tmp[8]==1){
        return res+1; 
    } 
    if(tmp[0]==1&&tmp[3]==1&&tmp[6]==1){
        return res+1;
    }
    if(tmp[1]==1&&tmp[4]==1&&tmp[7]==1){
        return res+1; 
    }
    if(tmp[2]==1&&tmp[5]==1&&tmp[8]==1){
        return res+1;
    } 
    if(tmp[0]==1&&tmp[4]==1&&tmp[8]==1){
        return res+1;
    }
    if(tmp[2]==1&&tmp[4]==1&&tmp[6]==1){
        return res+1;
    }
    //Bob
    if(tmp[0]==2&&tmp[1]==2&&tmp[2]==2){
        return -(res+1);
    }
    if(tmp[3]==2&&tmp[4]==2&&tmp[5]==2){
        return -(res+1);
    }
    if(tmp[6]==2&&tmp[7]==2&&tmp[8]==2){
        return -(res+1);
    } 
    if(tmp[0]==2&&tmp[3]==2&&tmp[6]==2){
        return -(res+1);
    }
    if(tmp[1]==2&&tmp[4]==2&&tmp[7]==2){
        return -(res+1);
    }
    if(tmp[2]==2&&tmp[5]==2&&tmp[8]==2){
        return -(res+1);
    } 
    if(tmp[0]==2&&tmp[4]==2&&tmp[8]==2){
        return -(res+1);
    }
    if(tmp[2]==2&&tmp[4]==2&&tmp[6]==2){
        return -(res+1);
    }
    //Tie
    if(res==0) return 0;
    //None
    return inf;
    
}

int dfs(int s,int p){
    if(ans[s][p]!=inf) return ans[s][p];
    vector<int> tmp;
    for(int i=0;i<9;i++) tmp.push_back(0);
    int ss=s;
    int cnt=0;
    while(ss){
        tmp[cnt]=ss%3;
        ss/=3;
        cnt++;
    }
    int x=judge(tmp);
    if(x!=inf) return ans[s][p]=x;
    if(p==0){
        int res=-inf;
        for(int i=0;i<9;i++){
            if(tmp[i]==0){
                res=max(res,dfs(s+1*three[i],1));    
            }
        }
        return ans[s][p]=res;
    }else{
        int res=inf;
        for(int i=0;i<9;i++){
            if(tmp[i]==0){
                res=min(res,dfs(s+2*three[i],0));
            }
        }
        return ans[s][p]=res;
    }
}
int main(){
    int T;
    scanf("%d",&T);
    pre(); 
    while(T--){
        for(int i=0;i<maxn;i++){
            ans[i][0]=ans[i][1]=inf;
        }
        for(int i=0;i<9;i++) scanf("%d",&a[i]);
        int s=0;
        for(int i=0;i<9;i++){
            s+=a[i]*three[i];
        }
        int ans=dfs(s,0);
        printf("%d
",ans);
    }
    return 0;
}