HDOJ 1536 S-Nim
2011-08-07 18:30
260 查看
首先,S-Nim是经典的博弈类的题目可以用Sprague-Grundy函数进行解决,关于Sprague-Grundy函数的方法,见链接文章:Sprague-Grundy函数
其次,关于Sprague-Grundy函数的SG值。S-Nim类的游戏转化为Nim游戏,并将每个点当做一堆石子,该点的SG值当做该堆的石子数。但是为什么SG值有什么意义?为什么可以转化为石子数?只有理解了SG值的确切意义才能完全明白为什么S-Nim向Nim的转化。看一下以下例子:
SG=g(x)={0,1,2,3}=4 ............................................. ①
SG=g(x)={0,1,2,3,5}=4 ..............................................②
SG=g(x)={1,2,3,5}=0 .................................................③
对比①和②可以发现,SG值似乎丢失了一些信息,②中的5值并没有通过SG值表示出来。对比②和③可以发现,③中信息似乎完全丢失了。但,是不是真的如此呢?回到博弈类题目的出发点:
一、博弈题目依据什么推测最终的输赢?
答:依据的是当前点处于必胜点,还是必败点。除此之外无需假借任何条件。
二、必胜点与必败点有什么性质。
答:(1) 所有终结点是必败点(P点);
(2) 从任何必胜点(N点)操作,至少有一种方法可以进入必败点(P点);
(3)无论如何操作, 从必败点(P点)都只能进入必胜点(N点).
然后,看一下SG值,SG值为零的点,则为P点(即,必败点),否则为N点(即,必胜点)。以上SG值的性质满足必败点与必胜点的所有性质:(1)所有终结点的SG值为零,为必败点。(2)若SG值不为零,则其为必胜点。设其值为m,则有SG=g(x)={0,1,2,....m-1}=m,大括号中的0为其后继点的SG值,即该点为必败点。所以满足从必胜点至少有一种方法进入必败点。(3)若,SG值为零的点不是终结点,则必存在一个值为m的点,使得SG=g(x)={...,m,...},大括号中的m为其后继点的SG值,即该点为必胜点。所以满足从必败点都只能进入必胜点。
综上所诉,SG值为零的点,则为P点(即,必败点),否则为N点(即,必胜点)。满足必胜点与必败点所有的性质。并且可以作为推测输赢的依据。例②中所谓的信息丢失并不存在,因为SG值仅仅关注零和非零,其重点在于后继点的SG值中是否存在零。例③中的信息同样并未丢失,因为其SG值为零恰恰表明了后继点中有不为零的值存在(或无后继点),而必败点仅仅关心这一点信息。所以SG值仅有两个意义,零和非零,标明了该点为必胜点还是必败点。因为石子的数量与SG值起到的相同的作用(标明必胜点或者必败点),因此S-Nim类题目转化为Nim类题目时可以将SG值与石子数量同等对待,更是因为如此S-Nim题目才可以转化为Nim类题目。
有了以上转换S-Nim就不难搞定了,代码贴上来:
View Code
其次,关于Sprague-Grundy函数的SG值。S-Nim类的游戏转化为Nim游戏,并将每个点当做一堆石子,该点的SG值当做该堆的石子数。但是为什么SG值有什么意义?为什么可以转化为石子数?只有理解了SG值的确切意义才能完全明白为什么S-Nim向Nim的转化。看一下以下例子:
SG=g(x)={0,1,2,3}=4 ............................................. ①
SG=g(x)={0,1,2,3,5}=4 ..............................................②
SG=g(x)={1,2,3,5}=0 .................................................③
对比①和②可以发现,SG值似乎丢失了一些信息,②中的5值并没有通过SG值表示出来。对比②和③可以发现,③中信息似乎完全丢失了。但,是不是真的如此呢?回到博弈类题目的出发点:
一、博弈题目依据什么推测最终的输赢?
答:依据的是当前点处于必胜点,还是必败点。除此之外无需假借任何条件。
二、必胜点与必败点有什么性质。
答:(1) 所有终结点是必败点(P点);
(2) 从任何必胜点(N点)操作,至少有一种方法可以进入必败点(P点);
(3)无论如何操作, 从必败点(P点)都只能进入必胜点(N点).
然后,看一下SG值,SG值为零的点,则为P点(即,必败点),否则为N点(即,必胜点)。以上SG值的性质满足必败点与必胜点的所有性质:(1)所有终结点的SG值为零,为必败点。(2)若SG值不为零,则其为必胜点。设其值为m,则有SG=g(x)={0,1,2,....m-1}=m,大括号中的0为其后继点的SG值,即该点为必败点。所以满足从必胜点至少有一种方法进入必败点。(3)若,SG值为零的点不是终结点,则必存在一个值为m的点,使得SG=g(x)={...,m,...},大括号中的m为其后继点的SG值,即该点为必胜点。所以满足从必败点都只能进入必胜点。
综上所诉,SG值为零的点,则为P点(即,必败点),否则为N点(即,必胜点)。满足必胜点与必败点所有的性质。并且可以作为推测输赢的依据。例②中所谓的信息丢失并不存在,因为SG值仅仅关注零和非零,其重点在于后继点的SG值中是否存在零。例③中的信息同样并未丢失,因为其SG值为零恰恰表明了后继点中有不为零的值存在(或无后继点),而必败点仅仅关心这一点信息。所以SG值仅有两个意义,零和非零,标明了该点为必胜点还是必败点。因为石子的数量与SG值起到的相同的作用(标明必胜点或者必败点),因此S-Nim类题目转化为Nim类题目时可以将SG值与石子数量同等对待,更是因为如此S-Nim题目才可以转化为Nim类题目。
有了以上转换S-Nim就不难搞定了,代码贴上来:
View Code
//#include <fstream> #include <iostream> #include <algorithm> using namespace std; int f[10001]; unsigned set[101]; int setNum; int mex(int v) { bool g[101]={0}; for (int i=0;i<setNum;i++) { int t=v-set[i]; if(t<0) break; if(f[t]==-1) f[t]=mex(t); g[f[t]]=1; } for (int i=0;i<101;i++) { if(!g[i]) return i; } } int main() { //ifstream cin("S-Nim.txt"); while(cin>>setNum,setNum) { for(int i=0;i<setNum;i++) cin>>set[i]; sort(set,set+setNum); memset(f,-1,sizeof(f)); f[0]=0; int caseNum; cin>>caseNum; while(caseNum--) { int num; cin>>num; int s=0,value; while(num--) { cin>>value; if(f[value]==-1) f[value]=mex(value); s=s^f[value]; } if(s==0) cout<<"L"; else cout<<"W"; } cout<<endl; } }
相关文章推荐
- HDOJ 1536 S-NIM
- HDOJ 1536 S-Nim解题报告
- HDOJ 1536 S-Nim 博弈 SG函数
- HDOJ-1536 S-Nim
- HDOJ 1536 S-Nim
- 【HDOJ1536】S-Nim(博弈)
- hdu 1536、hdu 1944 S-Nim(博弈SG函数)
- HDU 1536(sg博弈) S-Nim
- (SG函数)S-Nim--HDOJ
- HDU1536-nim
- hdu 1536 S-Nim(SG函数)
- 【HDU】1536 S-Nim
- HDOJ 1730 Northcott Game(nim博弈)
- hdu 1536/ hdu 1944 S-Nim(sg函数)
- hdoj1536 find the safest road(dijstra)
- hdu 1536 S-Nim(SG函数)
- hdu 1536 S-Nim_求sg值模版
- HDOJ 1536 SG函数的基本应用
- HDOJ 3032 Nim or not Nim? (博弈 :SG)
- HDOJ 题目1509 Be the Winner(anti-nim)