Codeforces 918D - MADMAX
思路:
dp+记忆化搜索
状态:dp[i][j][w]表示先手在i节点,后手在j节点,这一轮的字母为w的结果,如果为true,则表示先手必赢,否则后手必赢。
状态转移:如果i连的一条边的权值tw>=w,连向t,那么这个博弈的结果可以由dp[j][t][tw]决定,如果dp[j[t][tw]为false,那么dp[i][j][w]肯定为true(因为先手可以选择走这条边使对于对方来说后手必赢),如果不为false,可以选择不走这条路,如果所有边走过去都不能使dp[i][j][w]为true,那么dp[i][j][w]只能为false。
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) const int N=105; struct edge{ int to,w,next; }edge[N*N]; int head[N]; int dp[N][N][26]; int cnt=0; void add_edge(int u,int v,int w){ edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } bool dfs(int u,int v,int w){ if(dp[u][v][w]!=-1)return dp[u][v][w]; dp[u][v][w]=false; for(int i=head[u];~i;i=edge[i].next){ if(edge[i].w>=w&&!dfs(v,edge[i].to,edge[i].w)){ dp[u][v][w]=true; break; } } return dp[u][v][w]; } int main(){ ios::sync_with_stdio(false); cin.tie(0); int n,m,u,v; char c; mem(head,-1); mem(dp,-1); cin>>n>>m; for(int i=0;i<m;i++){ cin>>u>>v>>c; add_edge(u,v,c-'a'); } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(dfs(i,j,0))cout<<'A'; else cout<<'B'; } cout<<endl; } return 0; }