<题目链接>
题目大意:
给定一个DAG图,其中图的边权是给定的字符所对应的ascii码,现在A先手,B后手,每次沿DAG图走一步,但是第i次走的边权一定要大于等于第i-1次走的边权(这里是值两个人一起的第$i$次,不是一个人走动的第$i$次),最先无法走动的人输。让你对$A,B$的起始位置邻接矩阵$(i,j)$(代表A从$i$点出发,$B$从$j$点开始出发),对应给出他们的胜负情况,如果A胜,输出A,反之,输出B。
解题分析:
$dp[x][y][k]$表示先手$x$,后手$y$,边权为$k$对应的胜负情况。
对于$x$所有能够直接到达的点$v$,状态转移为$dp[y][v][nowval]$,前一个状态的后手$y$变成了当前的先手状态,$nowval$表示$x->v$的边权。
如果存在至少一个$v$,使得$dp[y][v][nowval]$为必败状态,则上一个状态$dp[x][y][k]$为必胜状态(因为他们都是选择最优的情况走)。
$dp[x][y][k]=0$表示先手必败,反之则必胜。
总时间复杂度为:$O(|sigma|*n*(n+m))$
#include <bits/stdc++.h> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define fi first #define se second #define pb push_back const int N = 110; int dp[N][N][130]; typedef pair<int,int>P; vector<P>G[N]; int n,m; bool DP(int x,int y,int k){ if(dp[x][y][k]!=-1)return dp[x][y][k]; for(int i=0;i<G[x].size();i++){ int v=G[x][i].fi,cost=G[x][i].se; if(cost>=k && DP(y,v,cost)==0) //如果下一步存在先手必败的情况,则这一步先手必胜 return dp[x][y][k]=1; } return dp[x][y][k]=0; //为0表示先手必败 } int main(){ cin>>n>>m; rep(i,1,m) { int u,v;char c;cin>>u>>v>>c; G[u].pb(P(v,c)); } memset(dp,-1,sizeof dp); rep(i,1,n) rep(j,1,n){ DP(i,j,0); } rep(i,1,n) { rep(j,1,n) printf("%c",dp[i][j][0]?‘A‘:‘B‘); puts(""); } }
原文地址:https://www.cnblogs.com/00isok/p/10799454.html
时间: 2024-11-01 12:29:04