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);
    }
}
时间: 2024-08-01 17:59:11

codeforce gym 100548H The Problem to Make You Happy的相关文章

Gym - 100548H The Problem to Make You Happy 2014-2015 ACM-ICPC, Asia Xian Regional Contest (BFS+博弈)

题意:Bob和Alice在一张有向无环图上移动,给定二者的起点,Bob先手.Bob的失败条件是不能移动或者与Alice相遇.两个人都采取最优策略,求Bob是否会赢 分析:银牌题.先确定所有的失败状态,然后根据这些反向状态BFS. 用\(dp[i][j][0or1]\)表示bob在i点,Alice在j点,当前移动的人是bob还是Alice的情况, bob是否必败. 首先能确定的是 \(dp[i][j][0] = dp[i][j][1] = 0\), 对于出度为0的点\(i\),\(dp[i][j]

codeforce gym 100307H Hack Protection

原题地址:http://codeforces.com/gym/100307/problem/H 题意: 给定一个序列,求序列的子区间中,满足子区间XOR值等于AND值得子区间个数. 题解: 一直以为NEERC这种有名的比赛应该题解到处都是,太天真了…… 首先考虑区间的AND值. 对于固定起点的区间,因为 & 的性质,AND值必然单调递减,并且,根据AND值中1的个数划分后面的区间,必然最多只能划分成32段,对于某一段中的任意位置,它和固定的起点所形成的子区间的AND值是一样的. 再来考虑区间的X

CF GYM 100548 The Problem Needs 3D Arrays(2014ACM西安现场赛Problem C)

ProblemC. The Problem Needs 3D Arrays Description A permutation is asequence of integers p1, p2, . . . , pn,consisting of n distinct positive integers and each of them does notexceed n. Assume that r(S) of sequence S denotes the number ofinversions i

CF GYM 100548 The Problem to Make You Happy(2014ACM西安现场赛Problem H)

ProblemH. The Problem to Make You Happy Description Alice and Bob aregood friends, as in every other storyline. One day Alice and Bob areplaying an interesting game. The game is played on a directedgraph with n vertices and m edges, Alice and Bob hav

Gym - 100548C The Problem Needs 3D Arrays

Problem C.   The Problem Needs 3D Arrays Time Limit: 6000MS Memory Limit: 262144KB 64bit IO Format: %I64d & %I64u Description A permutation is a sequence of integers p1,p2,...,pn, consisting of n distinct positive integers and each of them does not e

codeforce Gym 100418K Cards (概率,数学)

题意:麦田的故事,n张牌,取x张牌,记住前x张牌最大的值m,继续往后取,遇到第一张比m大的牌就停下来.求一个x使得最后的牌在整副牌里是最大的期望最大. 假设最大的牌是A,A在各种位置出现的概率就是相等的,在A固定的情况下,在它前面的牌中最大的牌B,出现在各个位置的概率也是相等的.所以就是要求一个X,使得 下面这个矩形框中的概率和最大. 样例,n=5 #include<bits/stdc++.h> int main() { int n;scanf("%d",&n);

codeforce Gym 100685E Epic Fail of a Genie(贪心)

题意:给出一堆元素,求一个子集,使子集的乘积最大,如有多个,应该使子集元素个数尽量小. 题解:贪心,如果有乘积大于1的正数,那么是一定要选的,注意负数也可能凑出大于1的正数,那么将绝对值大于1的负数两两配对,如果还剩下一个,那么在判断一下,那个负数和比它小的最小负数的乘积是否大于1,如果是那么就选这两个.把所有可能凑成大于1的数选完以后,剩下的数一定比1小,那么就不选. 如果无法凑出大于1的数,那么再分类讨论一下. 挺容易写错... #include<bits/stdc++.h> using

codeforce Gym 101102A Coins (01背包变形)

01背包变形,注意dp过程的时候就需要取膜,否则会出错. 代码如下: #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define MAXW 15005 #define N 155 #define LL long long #define MOD 1000000007 int w1[N],w2[N]; LL dp1[MAXW],dp2[MAXW]; int main(

codeforce Gym 100342J Triatrip (bitset)

傻逼题,但是为什么别人的O(n^3)不会T?只是因为用了bitset优化... 附上一张bitset基本操作的表 #include<bits/stdc++.h> using namespace std; const int maxn = 1500+2; char g[maxn][maxn]; bitset<maxn> b1[maxn],b2[maxn],res; #define local int main() { #ifdef local freopen("triatr