abc349E Weighted Tic-Tac-Toe 博弈论+搜索
最开始学博弈论的时候学到过博弈论里的一个基本定理
1.当前局面先手必胜当且仅当后续局面存在先手必败
2.当前局面先手必败当且仅当后续局面全是先手必胜
当时就想着用搜索做,但是局面太多了搜不过来,所以后面又学了SG函数啥的。
但是这个题很明显可以搜索。
#include<bits/stdc++.h>
#define int long long
#define ULL unsigned long long
#define DB double
using namespace std;
int n,l,r,cnt;
int a[5][5],se[5][5];
int ying(int s) // 看看是不是s连成三个
{
if(se[1][1]==s&&se[2][2]==s&&se[3][3]==s)return 1;
if(se[3][1]==s&&se[2][2]==s&&se[1][3]==s)return 1;
if(se[1][1]==s&&se[1][2]==s&&se[1][3]==s)return 1;
if(se[2][1]==s&&se[2][2]==s&&se[2][3]==s)return 1;
if(se[3][1]==s&&se[3][2]==s&&se[3][3]==s)return 1;
if(se[1][1]==s&&se[2][1]==s&&se[3][1]==s)return 1;
if(se[1][2]==s&&se[2][2]==s&&se[3][2]==s)return 1;
if(se[1][3]==s&&se[2][3]==s&&se[3][3]==s)return 1;
return 0;
}
int check() // 看看是否没有连成三个
{
if(ying(1))return 1;
if(ying(2))return 2;
return 0;
}
int sum(int x) // 没有连成三个就算一下得分的和
{
int res=0;
for(int i=1;i<=3;++i)
for(int j=1;j<=3;++j)
if(se[i][j]==x)res+=a[i][j];
return res;
}
int dfs(int bu,int ren) // 现在是第几步,哪个人先手
{
if(check()!=0)
{
return check()==ren;
}
if(bu==10)
{
if(sum(2)>sum(1))return 1;
else return 0;
}
for(int i=1;i<=3;++i)
for(int j=1;j<=3;++j)
if(se[i][j]==0)
{
se[i][j]=ren;
if(dfs(bu+1,3-ren)==0)
{
se[i][j]=0;
return 1;
}
se[i][j]=0;
}
return 0;
}
signed main()
{
for(int i=1;i<=3;++i)
for(int j=1;j<=3;++j)cin>>a[i][j];
if(dfs(1,1))printf("Takahashi");
else printf("Aoki");
return 0;
}
/*
-1 1 0
-4 2000 -5
-4 -1 -5
*/