CF917B MADMAX
Posted Jozky86
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF917B MADMAX相关的知识,希望对你有一定的参考价值。
题意:
Alice和Bob有一个n个点m条边的DAG,每条边上有一个小写英文字母表示权值,Alice和Bob每人有一个棋子,每个人放在一个节点上(可以放在同一个节点上)。 第一轮Alice可以沿一条边把棋子移到一个相邻的节点上,之后Bob沿一条边移动棋子,以此类推,规则规定:每一次移动经过的边的ASCII码单调不降(即,若Alice沿’c’走了一步,Bob只能沿’c’或’c’之后的字母走,然后Alice又要沿Bob走过的字母之后的字母走…)。不能走的人输掉这盘游戏。 现在他们想知道,给定初始位置,两人都按最优策略,谁会赢?
题解:
枚举起点,正常模拟博弈过程
sg[x][y][kw]:先手为x,后手为y,字母限制不超过kw的这个状态的sg值
如果sg==0说明先手输,sg=1说明先手赢
v是u的下一个状态
如果全部sg[v]是1,sg[u]为0
如果存在sg[v]是0,sg[u]为1
上面这两个条件怎么实现呢?
我们令sg[u]为0,然后去找v,如果有一个v使得sg[v]是0,说明sg[v]=1
当不能走时即输掉比赛,此时sg为0
dfs模拟过程,记忆化搜索+dp实现
复杂度O(26 * N^2 + 26 * N * M)
26 * N * N是枚举起点
26 * N * M是dfs
代码:
#include<bits/stdc++.h>
#define INF (1<<25)
#define MAXN 105
#define LL long long
using namespace std;
int N,M;
struct edge{
int v,w;
edge(int v=0, int w=0):v(v), w(w){}
};
vector<edge> adj[MAXN];
int sg[MAXN][MAXN][26];
//sg = 0/1 lose/win
//sg[u] = 0, if all sg[v] = 1
//sg[u] = 1, if some sg[v] = 0
bool dfs(int x, int y, int kw){
if(sg[x][y][kw] != -1) return sg[x][y][kw];
sg[x][y][kw] = 0;
int v,w;
for(int k=0;k<adj[x].size();k++){
v = adj[x][k].v;
w = adj[x][k].w;
if(w < kw) continue;//必须满足字母非上升序列
if(dfs(y,v,w)==0){
sg[x][y][kw] = 1;
break;
}
}
return sg[x][y][kw];
}
int main(){
cin>>N>>M;
int u,v;
char c;
for(int i=1;i<=M;i++){
cin>>u>>v>>c;
adj[u].push_back(edge(v,c-'a'));
}
memset(sg,-1,sizeof(sg));//初始化为-1
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;
}
以上是关于CF917B MADMAX的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 918D MADMAX 图上dp 组合游戏