算法分析
博弈论sg函数 + 记忆化搜索
表示为 先手在 u 点 后手在 v 点 上一次操作的权值为 w 时,先手的胜负状况
考虑sg函数必胜必败态转移
sg的状态转移其实像是图上的dp转移
会转移到哪里呢,当前的先手为 u 后手为 v ,限制条件为 w
那么轮到 v 的这一轮时 先手就是 v ,后世就是 u 再往后任意走一个位置(我在这里假设成 e
并且到这个位置的权值要大于 w
那么就是转移到看 上,因为上一步是 u 走的一步权值为
的一步
那么记忆化搜索的过程就出来了
bool dfs(int u,int v,int w)
{
if(vis[u][v][w]) return dp[u][v][w];
vis[u][v][w] = 1;
for(auto e : g[u])
{
if(e.second < w) continue;//不符合条件
if(!dfs(v,e.first,e.second)) return dp[u][v][w] = true;
}
return dp[u][v][w] = false;
}
AC Code
#include<bits/stdc++.h>
using namespace std;
const int N = 110;
int dp[N][N][28],vis[N][N][28];
vector<pair<int,int>> g[N];
bool dfs(int u,int v,int w)//记忆化搜索
{
if(vis[u][v][w]) return dp[u][v][w];//访问过 直接返回
vis[u][v][w] = 1;//标记已经访问
for(auto e : g[u])//转移下一个状态
{
if(e.second < w) continue;
if(!dfs(v,e.first,e.second)) return dp[u][v][w] = true;
//如果轮到 v 这一轮走的时候 走不了了 那么 u 就赢了
}
return dp[u][v][w] = false;//否则就输了
}
int main()
{
int n,m;
cin >> n >> m;
for(int i = 1;i <= m;i ++)
{
int u,v;char c;
cin >> u >> v >> c;
g[u].push_back({v,c - 'a'});
}
for(int i = 1;i <= n;i ++)
{
for(int j = 1;j <= n;j ++)
cout << (dfs(i,j,0) == true ? "A" : "B");
cout <<"\n";
}
return 0;
}