zoukankan      html  css  js  c++  java
  • 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("
    ");
    44     }
    45 
    46     return 0;
    47 }

      

    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    单表通用excle导入(只要是单表都可以,只需要传文件跟表名及用户id即可)
    单表通用excle导出(只要是单表都可以)
    mysql数据库中的mybatis中xml解决in不起作用的问题
    Mysql获取系统时间,年,月,日
    Linux下MySQL的数据库安装
    MP3音频文件的剪切合并方法
    Oracle client客户端简易安装网上文档一
    excel导出功能
    Oracle数据库的创建表全
    Oracle表字段的增加、删除、修改和重命名
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/8433266.html
Copyright © 2011-2022 走看看