[原博客] POJ 2425 A Chess Game

题目链接
题意:给定一个有向无环图(DAG),上面放有一些旗子,旗子可以重合,两个人轮流操作,每次可以把一个旗子从一个位置移动到相邻的位置,无法移动时输,询问先手是否必胜。

这道题可以把每个旗子看作单独的一个游戏,那么所有这些旗子的状态SG值,就是这些旗子各自SG值的Xor和,可以记忆化搜索dfs,暴力算SG值判断即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>

//by zrt
//problem:
using namespace std;
typedef long long LL;
const int inf(0x3f3f3f3f);
const double eps(1e-9);
int n;
int H[1005],X[1000005],P[1000005],tot;
inline void add(int x,int y){
    P[++tot]=y;X[tot]=H[x];H[x]=tot;
}
int sg[1005];
int dfs(int x){
    if(~sg[x]) return sg[x];
    bool nxt[1005];
    memset(nxt,0,sizeof nxt);
    for(int i=H[x];i;i=X[i]){
        nxt[dfs(P[i])]=1;
    }
    for(int i=0;;i++){
        if(!nxt[i]){
            return sg[x]=i;
        }
    }
}
int main(){
    #ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    while(~scanf("%d",&n)){
        memset(H,0,sizeof H);tot=0;
        memset(sg,-1,sizeof sg);
        for(int i=0,x;i<n;i++){
            scanf("%d",&x);
            for(int j=0,y;j<x;j++){
                scanf("%d",&y);
                add(i,y);
            }
        }
        int q;
        while(scanf("%d",&q),q){
            int SG=0;
            for(int i=0,x;i<q;i++){
                scanf("%d",&x);
                SG^=dfs(x);
            }
            if(SG) puts("WIN");
            else puts("LOSE");
        }
    }
    return 0;
}

时间: 2024-10-30 23:22:19

[原博客] POJ 2425 A Chess Game的相关文章

[原博客] POJ 1067 取石子游戏

题目链接有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相同数量的石子.最后把石子全部取完者为胜者.现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者.(中文题面,感动ing) 但是这道题实在是呵呵.开始没啥思路,根据必胜状态必败状态的定义,n^3打了个表,看起来是这样的. 图为100x100,已经缩小,左上角是状态(0,0),右下角状态为(10

[原博客] POJ 2975 Nim 统计必胜走法个数

题目链接题意介绍了一遍Nim取石子游戏,可以看上一篇文章详细介绍.问当前状态的必胜走法个数,也就是走到必败状态的方法数. 我们设sg为所有个数的Xor值.首先如果sg==0,它不可能有必胜走法,输出0. 对于任意一堆有a[i]个石子,若sg Xor a[i] <= a[i] ,那么我们就可以在a[i]里面取出sg Xor a[i]个石子,使得剩下石子Xor和为0,于是ans++.然后输出ans. 注意C/C++语言中^操作比<操作优先级低. #include<iostream> #

[原博客] POJ 1704 Georgia and Bob

题目链接题意:如图,Georgia和Bob在玩游戏.一个无限长的棋盘上有N个旗子,第i个棋子的位置可以用Pi表示.现在Georgia先走.每个人每一次可以把一枚棋子向左移动任意个格子,但是不能超越其他棋子,也不能和其他棋子处在同一个格子里.如果轮到某一个人的时候Ta再也不能移动棋子了,就判负.现在每个测试数据给定一种情况,如果Georgia会赢,输出“Georgia will win”,如果Bob会赢,输出“Bob will win”,如果不确定,输出“Not sure”.两个人都知道获胜策略是

[原博客] POJ 2505 A multiplication game 组合游戏

题目链接题意: 有一个数p=1,甲乙两人轮流操作,每次可以把p乘2~9中的一个数,给定一个n,当一个人操作后p>=n,那么这个人赢,问先手是否必胜. 必胜状态:存在一种走法走到一个必败状态. 必败状态:后继状态都为必胜状态. 我们可以知道>=n的数都为必败状态,可以转移到>=n的最小的数为n/9(上取整),所以 n/9~n-1都为必胜态,同理n/9/2(都为上取整)为最小的必须转移到n/9~n-1(必胜状态)的状态,所以n/9/2~n/9-1为必败态,于是就可以这样推到1,看一下1是必胜

[原博客] POJ 1740 A New Stone Game

题目链接题意:有n堆石子,两人轮流操作,每次每个人可以从一堆中拿走若干个扔掉(必须),并且可以从中拿走一些分到别的有石子的堆里(可选),当一个人不能拿时这个人输.给定状态,问是否先手必胜. 我们参考普通取石子游戏可知,如果只有一堆,先手必胜.如果有两堆一样,先手必败,对称博弈,第一个人怎么取,第二个人也可以怎么取,直到第一个人无法取为止.如果有四堆两两一样,还是先手必败,第一个人无论如何取,第二个人可以再次取成两两一样.如果有2*k堆两两一样,还是先手必败.注意:除了上述情况,都是先手必胜.因为

[原博客] POJ 2484 A Funny Game

题目链接题意:有n个硬币排成一圈,两个人轮流操作,每次可以取走一个或者相邻的连个硬币(只算最开始相邻的,取之后才相邻的不算),问先手必胜还是必败. 这个题可以证明若n>=3,则先手必败.对称博弈若n>=3,先手第一次必然把这个环拆成一个链,然后无论这条链长度的奇偶,后手总是可以把这条链分成两条相等的链,于是先手在一条链上做什么,后手就可以做什么.知道先手无法操作,后手胜. #include<iostream> #include<cstdio> #include<a

[原博客] BZOJ 2242 [SDOI2011] 计算器

题目链接 noip级数论模版题了吧.让求三个东西: 给定y,z,p,计算Y^Z Mod P 的值. 给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数. 给定y,z,p,计算满足Y^x ≡ Z ( mod P)的最小非负整数. 其中P均为素数.来分着处理. 1 y^z%p 快速幂.推荐一种又快又好写的写法. 1 LL power_mod(LL a,LL b,LL p){ //get a^b%p 2 LL ret=1; 3 while(b){ 4 if(b&1) ret = re

&lt;转自原博客&gt; 可爱的字符串算法们

在非常强又非常关心学弟学妹学习的企鹅学长变态的考纲下,我们无奈中选择一起学习新姿势 first:KMP算法 这是一个小迪更过博客的算法,我就不好意思在这里献丑了,所以献上友链一份:http://rabbithu.xyz/index.php?title=2017-04-01-01 second:Trie树(字典树) 嘤嘤嘤,这就是我在oi小组讲的第一堂课了!?(虽然当天大家都很颓,但是算法的简单是毋庸置疑的!) 在有关字符串的问题中,我们会遇到一些子串啊~前缀啊~的问题,如果正常枚举遍历的话复杂度

poj 2425 A Chess Game grundy值

题意: 给一个拓扑图,在一些点上有棋子,两个玩家每次轮流将一颗棋子沿有向边移动一次,无法移动则失败. 分析: 理解nim和状态的grundy值两下就敲出来了. 代码: //poj 2425 //sep9 #include <iostream> #include <vector> using namespace std; const int maxN=1024; vector<int> g[maxN]; int vis[maxN]; int grundy[maxN]; i