题意:在一个有向无环图上有n个顶点,每一个顶点都只有一个棋子,有两个人,每次根据这个图只能将任意一颗棋子移动一步 ,如果到某一步玩家不能移动时,那么这个人就输. 分析:本题是最典型的有向无环图的博弈,利用dfs把所有顶点的SG值都计算出来,然后对每个棋子的SG值进行异或运算,如果 为0就是先手必败,否则就是先手必胜. 如果某个人移动到出度为0的顶点,那么他必败,在这里首先介绍一下什么是SG函数. 对于给定的有向无环图,定义图中每个顶点的Sprague-Grundy函数g如下:g(x) = mex…
一个拓扑结构的图,给定n个棋的位置,每次可以沿边走,不能操作者输. 已经给出了拓扑图了,对于每个棋子找一遍SG最后SG和就行了. /** @Date : 2017-10-13 20:08:45 * @FileName: HDU 1524 树上无环博弈 暴力SG.cpp * @Platform: Windows * @Author : Lweleth (SoungEarlf@gmail.com) * @Link : https://github.com/ * @Version : $Id$ */…
n个棋子,其中第k个是红色的,每个棋子只能往上爬,而且不能越过.重叠其他棋子,谁将红色棋子移到顶部谁赢. 由于只能往上爬,所以很像阶梯博弈.这题有2个限制,棋子不能重叠,有红棋存在 首先不考虑红色棋,那么我们可以视棋于棋间的距离为石子堆,这样棋子两两分组就是奇数堆,组与组间的距离就是偶数堆. 有个特殊情况k=2时,此时第一个区间石子数要减小1,不能移完,否则后手直接就能取胜了. /** @Date : 2017-10-13 23:13:24 * @FileName: HDU 4315 阶梯博弈变…
n*n棋盘,初始左上角有一个石头,每次放只能在相邻的四个位置之一,不能操作者输. 如果以初始石头编号为1作为后手,那么对于每次先手胜的情况其最后一步的四周的编号必定是奇数,且此时编号为偶数,而对于一个局面,每个人都可以操控方向以致走完整个棋盘,所以当棋盘总格数为偶数时,先手必胜,而为奇数时,后手必胜. /** @Date : 2017-10-13 21:22:47 * @FileName: HDU 1564 简单博弈.cpp * @Platform: Windows * @Author : Lw…
http://codeforces.com/contest/787/problem/C 题目大意:有一个长度为n的环,第1个位置是黑洞,其他都是星球.已知在星球上(不含第一个黑洞)有一位神.有两个人,每个人有一个集合的数字,两人进行游戏,每人每轮可以让神从一个星球向后移动x位(x为目前两个人所拥有的集合中的一个任意数字,数字可以重复选).请求出神在2~n的每一个位置上时,两人分别先手的输赢情况,先手胜利输出WIN,先手必败输出LOOS,会无限循环输出LOOP. 思路:经典的有向图博弈(可惜我不会…
题目链接 给出一个有向无环图, 上面放有一些棋子, 两个人轮流移动棋子, 当一个人无法移动时, 算输. 求出每一个点的sg值, 异或就可以.出度为0的点sg值为0. #include<bits/stdc++.h> using namespace std; #define pb(x) push_back(x) #define ll long long #define mk(x, y) make_pair(x, y) #define lson l, m, rt<<1 #define m…
题目:传送门. 题意:有n行,每行最多20个棋子,对于一个棋子来说,如果他右面没有棋子,可以移动到他右面:如果有棋子,就跳过这些棋子移动到后面的空格,不能移动的人输. 题解:状态压缩博弈,对于一行2^20-1种情况来说处理出每一种情况的后继状态,求出sg值,进行异或即可. #include <iostream> #include <cstdio> #include <cmath> #include <cstring> using namespace std;…
题意:一个N个点的拓扑图,有M个棋子,两个人轮流操作,每次操作可以把一个点的棋子移动到它的一个后继点上(每个点可以放多个棋子),直到不能操作,问先手是否赢. 思路:DFS求每个点的SG值,没有后继的点为必败点. 注意搜索中初始化的问题. #include<stdio.h> #include<string.h> ,M=N*N; struct node{ int v,next; }e[M]; int head[N],cnt,in[N],out[N],n,sg[N],p[N]; void…
SG函数!! 代码如下: #include<stdio.h> #include<cstring> #define I(x) scanf("%d",&x) ][],sg[]; int getsg(int n) { ) return sg[n]; ]) ; ]; memset(vis,,sizeof(vis)); ;i<=map[n][];i++) vis[getsg(map[n][i])]=; ; while(vis[i]) i++; return…
题目大意 : 在一个 有向无环图顶点上面有几个棋子, 2个人轮流操作, 每次操作就是找一个棋子往它能够移 动的地方移动一格, 不能操作的人输. 输入第一行 为一个 N , 表示有 N 个顶点 0 -> N-1 标记, 然后 接下来的N 行 代表 与第 i 行 相连的有哪几个顶点 , 每一行开头一个 M 表示 有M 哥点与 点 i 相连. 然后接下来是 任意个询问, 一开始 是一个 M, 表示棋盘初始有 M 个棋子, 接下来的 M 个数 表示顶点i 上 有棋子, M == 0 代表询问结束 解题思…