HDU1536 S-Nim

题目链接:https://vjudge.net/problem/HDU-1536

题目大意:

  给一个数集\(S\),稍微修改\(Nim\)游戏的规则:原本是能在一堆里面取任意个数的石子,现在变成只能取\(n(n \in S)\)个石子,当没得取石子时判负。对于给定的局面,问先手的胜负条件。

知识点:  博弈论

解题思路:

  首先引用贾志豪的论文《组合游戏略述——浅谈SG游戏的若干拓展及变形》里面介绍的几个概念、定理:

  游戏的和:考虑任意多个同时进行的\(SG\)组合游戏,这些\(SG\)组合游戏的和是这样一个\(SG\)组合游戏,在它进行的过程中,游戏者可以任意挑选其中的一个单一游戏进行决策,最终,没有办法进行决策的人输。

  在我们每次只能进行一步操作的情况下,对于任何的游戏的和,我们若将其中的任一单一\(SG\)组合游戏换成数目为它的\(SG\)值的一堆石子,该单一\(SG\)组合游戏的规则编程取石子游戏的规则(可以任意取,甚至取完),则游戏的和的胜负情况不变。

  由以上两条得到启发:我们可以把题目中的这个\(S-Nim\)游戏中的每一堆石子看成一个独立的取石子游戏(只能取数集\(S\)中的数目的石子),算出每个独立游戏的\(SG\)值,整个游戏的\(SG\)值即为各个子游戏的\(SG\)值的异或和。

  而\(SG\)函数有如下性质:

  (1)对于任意的局面,如果它的\(SG\)值为\(0\),那么它的任何一个后继局面的\(SG\)值不为\(0\);

  (2)对于任意的局面,如果它的\(SG\)值不为\(0\),那么它一定有一个后继局面的\(SG\)值为\(0\)。

  由此我们不难推出:当\(SG\)值为\(0\)时,先手必败;否则先手必胜。

AC代码:

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 int S[105],k;
 5 int sg[10005];
 6 int inp[105];
 7 bool vis[10005];
 8 void dfs(int rt){   //DFS求rt的SG值,注意要加记忆化。
 9     if(sg[rt]!=-1)  return;
10     for(int i=0;i<k&&rt-S[i]>=0;i++){
11         if(sg[rt-S[i]]==-1) dfs(rt-S[i]);
12     }
13     for(int i=0;i<=k;i++)  vis[i]=false;
14     for(int i=0;i<k&&rt-S[i]>=0;i++)
15         vis[sg[rt-S[i]]]=true;
16     for(int i=0;i<=rt;i++){
17         if(!vis[i]){
18             sg[rt]=i;
19             return;
20         }
21     }
22 }
23 int main(){
24     int l;
25     while(scanf("%d",&k)==1&&k){
26         for(int i=0;i<=10000;i++)   sg[i]=-1;
27         for(int i=0;i<k;i++)    scanf("%d",&S[i]);
28         sort(S,S+k);
29         for(int i=0;i<S[0];i++) sg[i]=0;
30         int m;
31         scanf("%d",&m);
32         while(m--){
33             scanf("%d",&l);
34             int tmp=0;
35             for(int i=0;i<l;i++){
36                 scanf("%d",&inp[i]);
37                 dfs(inp[i]);
38                 tmp^=sg[inp[i]];
39             }
40             if(tmp==0)  printf("L");
41             else    printf("W");
42         }
43         printf("\n");
44     }
45 
46     return 0;
47 }

 

  

posted @ 2018-02-08 21:27  Blogggggg  阅读(108)  评论(0编辑  收藏  举报