Nim 博弈和 sg 函数
sg 函数
几类经典的博弈问题
- 阶梯博弈: 只考虑奇数号楼梯Nim,若偶数楼梯只作容器,那么游戏变为Nim。题目
- 翻转硬币: 局面的SG值为局面中每个正面朝上的棋子单一存在时的SG值的异或和。题目
- Multi-SG游戏: 对于一个单一游戏,不同的方法可能会将其分成不同的多个单一游戏。每一方法对应的多个单一游戏的游戏的和即可以表示这种方法的NP状态。而这个单一游戏的SG函数即为未在所有方法的SG函数值中出现过的最小值。题目
- Anti-SG游戏和SJ定理 (在论文中有详细的论述和证明)
- Every-SG游戏: 对于Every-SG游戏先手必胜当且仅当单一游戏中最大的step为奇数。题目
- 树的删边游戏: 叶子节点的SG值为0;中间节点的SG值为它的所有子节点的SG值加1后的异或和。题目
- 无向图的删边游戏: 我们可以对无向图做如下改动:将图中的任意一个偶环缩成一个新点,任意一个奇环缩成一个新点加一个新边;所有连到原先环上的边全部改为与新点相连。这样的改动不会影响图的SG 值。
题目
hdu3032
题意
Multi-SG
给 n 堆石子, 每次有两步可选的操作,
- 将一堆 石子分成两堆
- 拿走一堆石子的任意个
最后不能行动的输。
分析
看完论文就会做了,
一堆石子数量为2 时 的后继有:0,1和(1,1),他们的SG值分别为0,1,0,所以sg(2) =2。
一堆石子数量为3 时的后继有:0、1、2、(1,2),他们的SG值分别为0、1、2、3,所以sg(3) = 4。
一堆石子数量为4 时的后继有:0、1、2、3、(1,3)和(2,2),他们的SG值分别为0,1,2,4,5,0,所以sg(4) = 3.
打表可以找到规律,见代码。
code
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 5;
const int INF = 1e9;
int vis[30], sg[30];
void init()
{
sg[0] = 0;
for(int i = 0; i < 30; i++)
{
memset(vis, 0, sizeof vis);
for(int j = 1; j < i; j++)
{
vis[sg[j] ^ sg[i - j]] = 1;
}
for(int j = 0; j < i; j++) vis[sg[j]] = 1;
for(int j = 0; ; j++)
{
if(!vis[j])
{
sg[i] = j;
printf("sg[%d]:%d\n", i, j);
break;
}
}
}
}
int main()
{
//init();
int T;
scanf("%d", &T);
while(T--)
{
int n;
scanf("%d", &n);
int ans = 0;
while(n--)
{
int x;
scanf("%d", &x);
if(x % 4 == 3) x++;
else if(x % 4 == 0) x--;
ans ^= x;
}
if(ans) puts("Alice");
else puts("Bob");
}
return 0;
}
hdu3595
题意
一共有n个游戏,每一个游戏有两堆石子,一次移动可以从大的那堆石子里拿小的那堆石子的整数倍的石子。只要是可以操作的游戏都要进行操作,不能进行操作的人负。
分析
Every-SG游戏,对于Every-SG游戏先手必胜当且仅当单一游戏中最大的step为奇数,通过dfs找到必败态和必胜态的转移,对于必胜态,尽可能的慢结束游戏,对于必败态尽可能快的结束游戏。
code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int INF = 1e9;
const int MAXN = 1e3 + 10;
int dp[MAXN][MAXN];
int dfs(int p, int q)
{
if(p > q) swap(p, q);
if(!p) return dp[p][q] = 0;
int k = q / p, tp = q % p, tq = p;
int flag = dfs(tp, tq);
if(k == 1)
{
dp[p][q] = dp[tp][tq] + 1;
return flag ^ 1;
}
else
{
if(!flag) dp[p][q] = dp[tp][tq] + 1;
else dp[p][q] = dp[tp][tq] + 2; // 后面存在一个不是终止态的必败态,这样至少会增加2步。
return 1;
}
}
int main()
{
int N;
memset(dp, -1, sizeof dp);
while(~scanf("%d", &N))
{
int ans = 0;
while(N--)
{
int p, q;
scanf("%d%d", &p, &q);
dfs(p, q);
ans = max(ans, dp[min(p, q)][max(p, q)]);
}
puts((ans & 1) ? "MM" : "GG");
}
return 0;
}
poj3710
题意
- 有 N个局部联通的图。
- Harry 和 Sally轮流从图中删边,删去一条边后,不与根节点相连的部分将被移走。Sally为先手。
- 图是通过从基础树中加一些边得到的。
- 所有形成的环保证不共用边,且只与基础树有一个公共点。
- 谁无法移动谁输。
分析
树的删边游戏,参见论文。
参考代码
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int INF = 1e9;
const int MAXN = 1e3 + 10;
int next[MAXN], head[MAXN], to[MAXN]; // 前向星
int vis[MAXN]; // 标记数组
// v[i]: 这里就解决了冲突,因为每添加一条边,其实是加入两条边,但是题目本身会存在重边的情况,注意到cnt初始化为1,第一条边是从2开始的,
// 这样每经过一条边,会把相应的v[i]和v[i^1]置为1,正好使得每条边只会被访问一次而不和题目的重边冲突。
int v[MAXN];
int w[MAXN]; // 标记环
int s[MAXN]; // 栈
int cnt, top;
int add(int u, int v)
{
to[++cnt] = v;
next[cnt] = head[u];
head[u] = cnt;
}
int dfs(int x)
{
vis[x] = 1;
s[++top] = x;
int ans = 0;
for(int i = head[x]; i; i = next[i])
{
if(!v[i])
{
v[i] = 1; v[i ^ 1] = 1;
int tmp = 0;
if(!vis[to[i]]) tmp = dfs(to[i]) + 1;
else
{
int q = s[top--];
while(q != to[i])
{
w[q] = 1;
q = s[top--];
}
top++;
return 1;
}
if(w[to[i]]) ans ^= (tmp & 1); // 本来要判断环的奇偶性,回溯的时候是0,1交替,010101...
else ans ^= tmp;
}
}
return ans;
}
int main()
{
int n;
while(~scanf("%d", &n))
{
int ans = 0;
while(n--)
{
memset(next, 0, sizeof next);
memset(head, 0, sizeof head);
memset(vis, 0, sizeof vis);
memset(v, 0, sizeof v);
memset(w, 0, sizeof w);
int m, k; cnt = 1; top = 0;
scanf("%d%d", &m, &k);
for(int i = 0; i < k; i++)
{
int x, y;
scanf("%d%d", &x, &y);
add(x, y);
add(y, x);
}
ans ^= dfs(1);
}
if(ans) puts("Sally");
else puts("Harry");
}
return 0;
}
Nim 博弈和 sg 函数的更多相关文章
- Nim 游戏、SG 函数、游戏的和
Nim游戏 Nim游戏定义 Nim游戏是组合游戏(Combinatorial Games)的一种,准确来说,属于“Impartial Combinatorial Games”(以下简称ICG).满足以 ...
- [您有新的未分配科技点]博弈论入门:被博弈论支配的恐惧(Nim游戏,SG函数)
今天初步学习了一下博弈论……感觉真的是好精妙啊……希望这篇博客可以帮助到和我一样刚学习博弈论的同学们. 博弈论,又被称为对策论,被用于考虑游戏中个体的预测行为和实际行为,并研究他们的应用策略.(其实这 ...
- Nim游戏与SG函数 ——博弈论小结
写这篇博客之前,花了许久时间来搞这个SG函数,倒是各路大神的论文看的多,却到底没几个看懂的.还好网上一些大牛博客还是性价比相当高的,多少理解了些,也自己通过做一些题加深了下了解. 既然是博弈,经典的N ...
- 数学:Nim游戏和SG函数
有若干堆石子,两人轮流从中取石子,取走最后一个石子的人为胜利者 以下的性质是显然的 .无法移动的状态是必败态 .可以移动到必败态的局面一定是非必败态 .在必败态做所有操作的结果都是非必败态 在普通Ni ...
- Nowcoder 挑战赛23 B 游戏 ( NIM博弈、SG函数打表 )
题目链接 题意 : 中文题.点链接 分析 : 前置技能是 SG 函数.NIM博弈变形 每次可取石子是约数的情况下.那么就要打出 SG 函数 才可以去通过异或操作判断一个局面的胜负 打 SG 函数的时候 ...
- 博弈论(nim游戏,SG函数)
说到自己,就是个笑话.思考问题从不清晰,sg函数的问题证明方法就在眼前可却要弃掉.不过自己理解的也并不透彻,做题也不太行.耳边时不时会想起alf的:"行不行!" 基本的小概念 这里 ...
- 【BZOJ1299】巧克力棒(Nim游戏,SG函数)
题意:TBL和X用巧克力棒玩游戏.每次一人可以从盒子里取出若干条巧克力棒,或是将一根取出的巧克力棒吃掉正整数长度. TBL先手两人轮流,无法操作的人输. 他们以最佳策略一共进行了10轮(每次一盒).你 ...
- hihoCoder hiho一下 第四十六周 博弈游戏·Nim游戏·三( sg函数 )
题意: 给出几堆石子数量,每次可以取走一堆中任意数量的石头,也可以将一堆分成两堆,而不取.最后取走者胜. 思路: 先规矩地计算出sg值,再对每个数量查SG值就可以了.最后求异或和.和不为0的就是必赢. ...
- 博弈论初步(SG函数)
讲解见此博客https://blog.csdn.net/strangedbly/article/details/51137432 理解Nim博弈,基于Nim博弈理解SG函数的含义和作用. 学习求解SG ...
随机推荐
- Jquery一些实用函数
1.jQuery.parseJSON( json )第一个参数json的类型是字符串: var obj = jQuery.parseJSON( '{ "name": "J ...
- Python 装饰器装饰类中的方法
title: Python 装饰器装饰类中的方法 comments: true date: 2017-04-17 20:44:31 tags: ['Python', 'Decorate'] categ ...
- 第五章 HQL实用技术
第五章 HQL实用技术5.1 使用HQL查询语句(面向对象查询语句) 5.1.1 编写HQL语句 5.1.1.1 from子句 例:fr ...
- java复习(9)---数据库JDBC
java写工程当然需要连接数据库.JDBC技术是连接数据库和应用程序的纽带,本节主要说明如何连接数据库. java中提供sql类. package re09; import java.sql.*; p ...
- junit测试Android项目
关于junit测试Android项目方法主要有一下步骤: 1.导入junit4的jar包 在工厂中Build Path中Add Library->JUnit->JUnit4->Fin ...
- Angular2.js——数据显示
显示数据,即属性绑定机制把数据显示到用户界面上. 在Angular中最典型的数据显示方式,就是把HTML模板中的控件绑定到Angular组件的属性. 接下来介绍几种数据显示的语法和代码片段. 使用插值 ...
- 分布式键值存储系统ETCD调研
分布式键值存储系统ETCD调研 简介 etcd是一个开源的分布式键值存储工具--为CoreOS集群提供配置服务.发现服务和协同调度.Etcd运行在集群的每个coreos节点上,可以保证coreos集群 ...
- JQuery速成大法
什么是JQuery呢,很多都是只闻其名. jQuery是一个快速.简洁的JavaScript框架,是一个优秀的JavaScript代码库.jQuery设计的宗旨是"write Less,Do ...
- jQuery常用代码片段
检测IE浏览器 在进行CSS设计时,IE浏览器对开发者及设计师而言无疑是个麻烦.尽管IE6的黑暗时代已经过去,IE浏览器家族的人气亦在不断下滑,但我们仍然有必要对其进行检测.当然,以下片段亦可用于检测 ...
- Vue项目的部署
通过vue-cli创建的工程,默认已经打好了基础,包含vue-loader webpack. 通常我们开发中,使用npm run dev进行开发,webpack会Hot reload,不用我们手动刷新 ...