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\n",iCase);
    else printf("Case #%d: No\n",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);
    }
}

 

posted on 2016-09-11 18:23  zhong_wang  阅读(425)  评论(0编辑  收藏  举报

导航