Nim博弈

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;
}

你可能感兴趣的:(博弈)