Nim 游戏的拓展、每次只能取限定个数个石子。 据说所有的组合游戏都可以转化为Nim游戏模型并用SG函数求解。
自己写了一遍SG函数的实现过程、感觉就是一个记忆化搜索的过程……
S-Nim
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3506 Accepted Submission(s): 1539
Problem Description
Arthur and his sister Caroll have been playing a game called Nim for some time now. Nim is played as follows:
The starting position has a number of heaps, all containing some, not necessarily equal, number of beads. The players take turns chosing a heap and removing a positive number of beads from it. The first player not able to make a move, loses. Arthur and Caroll really enjoyed playing this simple game until they recently learned an easy way to always be able to find the best move: Xor the number of beads in the heaps in the current position (i.e. if we have 2, 4 and 7 the xor-sum will be 1 as 2 xor 4 xor 7 = 1). If the xor-sum is 0, too bad, you will lose. Otherwise, move such that the xor-sum becomes 0. This is always possible. It is quite easy to convince oneself that this works. Consider these facts: The player that takes the last bead wins. After the winning player's last move the xor-sum will be 0. The xor-sum will change after every move. Which means that if you make sure that the xor-sum always is 0 when you have made your move, your opponent will never be able to win, and, thus, you will win. Understandibly it is no fun to play a game when both players know how to play perfectly (ignorance is bliss). Fourtunately, Arthur and Caroll soon came up with a similar game, S-Nim, that seemed to solve this problem. Each player is now only allowed to remove a number of beads in some predefined set S, e.g. if we have S =(2, 5) each player is only allowed to remove 2 or 5 beads. Now it is not always possible to make the xor-sum 0 and, thus, the strategy above is useless. Or is it? your job is to write a program that determines if a position of S-Nim is a losing or a winning position. A position is a winning position if there is at least one move to a losing position. A position is a losing position if there are no moves to a losing position. This means, as expected, that a position with no legal moves is a losing position.
Input
Input consists of a number of test cases. For each test case: The first line contains a number k (0 < k ≤ 100 describing the size of S, followed by k numbers si (0 < si ≤ 10000) describing S. The second line contains a number m (0 < m ≤ 100) describing the number of positions to evaluate. The next m lines each contain a number l (0 < l ≤ 100) describing the number of heaps and l numbers hi (0 ≤ hi ≤ 10000) describing the number of beads in the heaps. The last test case is followed by a 0 on a line of its own.
Output
For each position: If the described position is a winning position print a 'W'.If the described position is a losing position print an 'L'. Print a newline after each test case.
Sample Input
2 2 5
3 2 5 12 3 2 4 7 4 2 3 7 12 5 1 2 3 4 5 3 2 5 12 3 2 4 7 4 2 3 7 12 0
Sample Output
LWW
WWL
Source
Norgesmesterskapet 2004
Recommend
LL
至于S-Nim 为什么能向 Nim 转化。感觉这个分析很到位: 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类题目。(上述分析摘自: http://www.cnblogs.com/AdaByron/archive/2011/08/07/2200981.html )
#include
#include
#include
#include
using namespace std;
const int N = 100 + 10;
const int M = 1000 + 10;
int n;
int f[N],set[N];
int mex(int v)
{
int g[N]={0};
for(int i=0;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
{
if(!g[i])
return i;
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
if(n==0) break;
for(int i=0;i
scanf("%d",&set[i]);
sort(set,set+n);
memset(f,-1,sizeof(f));
f[0]=0;
int m;
scanf("%d",&m);
for(int i=0;i
{
int c,k,res=0;
scanf("%d",&c);
for(int j=0;j
{
scanf("%d",&k);
if(f[k] == -1)
f[k]=mex(k);
res ^= f[k];
}
res == 0 ? printf("L") : printf("W");
}
printf("\n");
}
return 0;
}
|