CF917B MADMAX

Posted Jozky86

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF917B MADMAX相关的知识,希望对你有一定的参考价值。

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

Codeforces 918D MADMAX 图上dp 组合游戏

Codeforces Round #459 (Div. 2):D. MADMAX(记忆化搜索+博弈论)

如何从后台弹出片段

cf 模拟

CF1435 游记