zoukankan      html  css  js  c++  java
  • codeforce gym 100548H The Problem to Make You Happy

    题意:

    Alice和Bob在一个有向图上玩游戏,每个人各自操作一个棋子,如果两个棋子走到一个点上,判定Bob输;如果轮到任何一方走时,无法移动棋子,判定该方输

    现在Bob先走,要求判断胜负

    题解

    模型上看是SG问题,但是通常的SG做法需要DP,但是考虑这不是DAG模型,普通的记忆化搜索写法会RE

    正解的DP做法:dp[i][j][k]:i,j是Bob,Alice的位置,k是目前轮到谁走了。

    开始将所有显然的Bob输的情况加入队列中,不断拓展,找到所有的Bob输的情况。

    转移类似SG

    #include<bits/stdc++.h>
    
    #define clr(x,y) memset((x),(y),sizeof(x))
    
    using namespace std;
    typedef long long LL;
    
    const int maxn=100;
    
    struct Node
    {
        int x1,x2;
        int turn; // 0:Bob 1:Alice
    };
    
    int n,m;
    int a,b;
    int num[maxn+5][maxn+5];
    int deg[maxn+5];
    bool mp[maxn+5][maxn+5];
    bool dp[maxn+5][maxn+5][2];
    queue <Node> Q;
    
    void solve(int iCase)
    {
        while (!Q.empty()) Q.pop();
    
        int u,v;
        clr(mp,0);
        clr(deg,0);
        for (int i=1;i<=m;++i)
        {
            scanf("%d%d",&u,&v);
            ++deg[u];
            mp[u][v]=true;
        }
        scanf("%d%d",&a,&b);
    
        clr(dp,-1);
    
        for (int i=1;i<=n;++i)
        {
            dp[i][i][0]=false;
            dp[i][i][1]=false;
            Q.push((Node){i,i,0});
            Q.push((Node){i,i,1});
        }
    
        for (int i=1;i<=n;++i)
        {
            if (deg[i]==0)
            {
                for (int j=1;j<=n;++j)
                {
                    if (i==j) continue;
                    dp[i][j][0]=false;
                    Q.push((Node){i,j,0});
                }
            }
        }
    
        clr(num,0);
        while (!Q.empty())
        {
            Node now=Q.front();
            Q.pop();
    
            int x1=now.x1;
            int x2=now.x2;
            int turn=now.turn;
    
            if (turn==0)
            {
                for (int i=1;i<=n;++i)
                {
                    if (mp[i][x2])
                    {
                        if (!dp[x1][i][1]) continue;
                        dp[x1][i][1]=false;
                        Q.push((Node){x1,i,1});
                    }
                }
            }
            else
            {
                for (int i=1;i<=n;++i)
                {
                    if (mp[i][x1])
                    {
                        ++num[i][x2];
                        if (num[i][x2]==deg[i]) //如果从i出发的所有的状态都是必败态,那么dp[i][x2][0]本身也是必败态
                        {
                            if (!dp[i][x2][0]) continue;
                            dp[i][x2][0]=false;
                            Q.push((Node){i,x2,0});
                        }
                    }
                }
            }
        }
    
        if (dp[a][b][0]) printf("Case #%d: Yes
    ",iCase);
        else printf("Case #%d: No
    ",iCase);
    }
    
    int main(void)
    {
        #ifdef ex
        freopen ("../in.txt","r",stdin);
        //freopen ("../out.txt","w",stdout);
        #endif
    
        int T;
        scanf("%d",&T);
    
        for (int i=1;i<=T;++i)
        {
            scanf("%d%d",&n,&m);
            solve(i);
        }
    }
  • 相关阅读:
    SQList基础+ListView基本使用
    Git本地上传口令
    记住用户名和登录密码+虚拟机没有root权限解决办法
    API+gir上传错误解决办法
    界面跳转+信息传递+AS中如何将ADV转移到其他盘中
    界面跳转
    Android学习——ListView
    开课第一周周总结
    体温上报APP——班级统计
    体温上报APP——打印
  • 原文地址:https://www.cnblogs.com/123-123/p/5862357.html
Copyright © 2011-2022 走看看