poj 3537 Crosses and Crosses 博弈论之grundy值

题意:

给1*n的格子,轮流在上面叉叉,最先画得3个连续叉叉的赢,问先手必胜还是必败。

分析:

求状态的grundy值(也就是sg值),具体怎么求详见代码,为什么这么求要自己想的,只可意会(别人都说去看game theory,呵呵)。

代码:

//poj 3537
//sep9
#include <iostream>
#include <set>
using namespace std;
int grundy[2048];
int h[2048];
int get_grundy(int n)
{
	if(n<0)
		return 0;
	if(grundy[n]!=-1)
		return grundy[n];
	int h[2048];
	memset(h,0,sizeof(h));
	for(int i=1;i<=n;++i){
		int t=get_grundy(i-3)^get_grundy(n-i-2);
		h[t]=1;
	}
	int i;
	for(i=0;h[i];++i);
	return grundy[n]=i;
}
int main()
{
	int n;
	memset(grundy,-1,sizeof(grundy));
	grundy[0]=0,grundy[1]=1,grundy[2]=1,grundy[3]=1;
	while(scanf("%d",&n)==1)
		if(get_grundy(n)!=0)
			puts("1");
		else
			puts("2");
	return 0;
} 
时间: 2024-12-22 19:46:56

poj 3537 Crosses and Crosses 博弈论之grundy值的相关文章

【POJ】【3537】Crosses and Crosses

博弈论 相当于放了x的位置,左右4格都不能再放x了,谁无处可放就输. n<=2000 直接枚举后继状态,暴力求SG函数即可. 例: 0000000->x..0000 / .x..000 / ..x..00 / 0..x..0 / 00..x.. 记忆化搜索写挂了……还是顺序DP靠谱= =(跟S-Nim类似的写法,暴力求SG函数) 1 Source Code 2 Problem: 3537 User: sdfzyhy 3 Memory: 692K Time: 141MS 4 Language:

博弈论:寻找先手必胜策略——Grundy值

选修了人工智能课程,老师布置了调研任务:Grundy,开始看了一些资料并没有看懂. 后来找到了一篇文,写的很棒,里面有好多博弈相关的问题与分析,分享出来给大家: http://endless.logdown.com/posts/2014/05/05/find-out-the-winning-strategies-of-the-game-nim-and-grundy-number-notes 这个服务器可能是外国的?打开的很慢,不要认为自己的网炸了...哈哈哈 下面就贴一点自己为了做海报(Grun

poj 2311 Cutting Game nim与状态的grundy值

题意: 给一个w*h的矩形,两人轮流只能沿格子的边缘横剪或竖剪,最先剪出1*1的格子的人获胜,问先手必胜还是必败. 分析: 此题要求对grundy值有理解.一个全局状态的grundy值是对游戏中某个状态的有效的描述,grundy值描述了当前状态的所有后继状态,比如n堆石子的nim游戏的grundy值是a1^a2^...an. 代码: //poj 2311 //sep9 #include <iostream> #include <set> using namespace std; c

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

poj 1079 Calendar Game(博弈论 SG)

Calendar Game Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2519    Accepted Submission(s): 1438 Problem Description Adam and Eve enter this year's ACM International Collegiate Programming Co

硬币游戏2&amp;&amp;Cutting Game——Grundy值

Grundy值 当前状态的Grundy值就是除任意一步所能转移到的状态的Grundy值以外的最小非负整数, 以硬币问题一为例,可写成: int init_grundy() { sg[0] = 0; for(int i = 1;i <= x;i++) //递推求前x个SG值 { set<int>st; for(int j = 0;j < k;j++) if(a[j] <= i) st.insert(sg[i - a[j]]); int g = 0; while(st.count

POJ 3537 Crosses and Crosses

http://poj.org/problem?id=3537 题目大意: 两人在1*N的格子上轮流画X,每一次可以在空白的格子上画X,如果一个玩家把三个X连起来,那么就获胜.你的任务是判断是先手胜还是后手. 思路: 在纸上画画你会发现,你画一个格子后,他的左边两个和右边两个是不能画的(如果存在) ,也就是说,你每画一次,那么就排除掉5个格子 所以分为左边i - 3和右边n- i- 2两个部分.用SG函数求解. #include<cstdio> #include<cstring> c

POJ 3537 Crosses and Crosses(SG/还未想完全通的一道SG)

题目链接 #include<iostream> #include<cstdio> #include<cstring> using namespace std; int sg[2010]; int get_sg(int n) { if(n<0) return 0; if(sg[n]!=-1) return sg[n]; bool vis[2010]; //莫名其妙! //vis[]数组要声明在函数里,如果放外面会WA memset(vis,0,sizeof(vis)

poj 3537 Crosses and Crosses (SG)

题意: 1 × n 个格子,每人每次选一个格子打上叉(不得重复),如果一个人画完叉后出现了连续的三个叉,则此人胜. 给n,判断先手胜还是先手败. 思路: 假设选择画叉的位置是i,则对方只能在前[1,i-3]中或[i+3,n]中选择画叉.子问题出现. 根据SG的定义,即可求出SG(N).看代码. 代码: int sg[2005]; int n; int dfs(int n){ if(n<0) return 0; if(sg[n]!=-1) return sg[n]; bool g[2005] =