• UVALive 4318 Navy maneuvers


    UVALive_4318

        与一般的在树上进行的选择往哪边走的游戏相比,这个题目不同之处在与每个点既可能成为自己的决策点,也可能成为对方的决策点,因此可以将每个点看成有两种状态,一种对应着博弈树中的max节点,另一种对应着博弈树中的min节点,然后从叶子节点开始向上dp,依次处理出每个节点在两种状态下的值。

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define MAXD 10010
    #define MAXM 1000010
    #define INF 0x3f3f3f3f
    int N, M, F, first[MAXD], e, next[MAXM], v[MAXM], dgr[MAXD], a[MAXD];
    int S, dp[MAXD][2], vis[MAXD];
    void add(int x, int y)
    {
        v[e] = y;
        next[e] = first[x], first[x] = e ++;    
    }
    void init()
    {
        int i, x, y;
        for(i = 1; i <= N; i ++) scanf("%d", &a[i]);
        memset(first, -1, sizeof(first[0]) * (N + 1)), e = 0;
        memset(dgr, 0, sizeof(dgr[0]) * (N + 1));
        for(i = 0; i < M; i ++)
        {
            scanf("%d%d", &x, &y);
            add(x, y), ++ dgr[y];
        }
        for(S = 1; dgr[S]; S ++);
    }
    void dfs(int cur)
    {
        int i;
        vis[cur] = 1;
        dp[cur][0] = INF, dp[cur][1] = -INF;
        for(i = first[cur]; i != -1; i = next[i])
        {
            if(!vis[v[i]]) dfs(v[i]);
            dp[cur][0] = std::min(dp[cur][0], dp[v[i]][1]);
            dp[cur][1] = std::max(dp[cur][1], dp[v[i]][0]);
        }
        if(dp[cur][0] == INF) dp[cur][0] = dp[cur][1] = 0;
        dp[cur][0] += a[cur], dp[cur][1] += a[cur];
    }
    void solve()
    {
        memset(vis, 0, sizeof(vis[0]) * (N + 1));
        dfs(S);
        printf("%s\n", dp[S][1] >= F ? "Victory" : "Glory");
    }
    int main()
    {
        while(scanf("%d%d%d", &N, &M, &F) == 3)
        {
            init();
            solve();    
        }
        return 0;
    }
  • 相关阅读:
    linq 读取xml
    c# 定时器 自动执行
    如何在一个人输入框中只输入数字
    如何去掉滚动条,
    如何计算任意值之间的随机数呢
    【P2387】魔法森林(SPFA非正解)
    【Luogu】P3203弹飞绵羊(分块)
    【Luogu】P3396哈希冲突(根号算法)
    【Luogu】P2801教主的魔法(分块)
    【Luogu】P3155叶子的染色(树形DP)
  • 原文地址:https://www.cnblogs.com/staginner/p/2665423.html
Copyright © 2020-2023  润新知