• Codeforces 917B MADMAX (DP+博弈)


    <题目链接>

    题目大意:
    给定一个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$表示先手必败,反之则必胜。

    #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("");
        }
    }
  • 相关阅读:
    Linux_进程之间的通信
    Linux_控制作业(管理)
    Linux_进程管理相关命令
    Linux_进程管理的基本概述
    文本编辑_Vim&Vi
    Linux_权限管理理论概述
    Linux_用户和组管理
    Linux_ACL文件访问控制列表
    72. VUE axios 配置信息相关
    71. VUE axios 发送并发请求(多个)
  • 原文地址:https://www.cnblogs.com/00isok/p/10799454.html
Copyright © 2020-2023  润新知