博弈论 ( Nim游戏+SG模板)——S-Nim ( HDU 1536 )

来源:互联网 发布:变声器男变女甜美软件 编辑:程序博客网 时间:2024/06/12 00:37
  • 题目链接:
    http://acm.hdu.edu.cn/showproblem.php?pid=1536

  • 分析:
    给出K种拿石子的方法,然后给出I堆石子让你判断当前位置是必胜点还是必败点。

  • 题解:
    对于每次给出的K种拿法,先用SG函数预处理一遍,然后直接异或每一堆石子的数量就能得到其最终结果

    SG函数模板:

const int MAX = 10005;//总的石子数int f[105], sg[MAX]; //f为可以操作的集合void get_sg(int n){    memset(sg, 0, sizeof(sg));    bool vst[MAX];    for(int i = 0; i < MAX; i++)    {        memset(vst, false, sizeof(vst));        int h = 0, j;        while(i >= f[h] && h < n)            vst[sg[i - f[h++]]] = true;        for(j = 0; j <= i; j++)        {            if(!vst[j])            {                sg[i] = j;                 break;            }        }    }    return ;}
  • AC 代码:
#include <iostream>#include <cmath>#include <cstdio>#include <algorithm>#include <cstring>using namespace std;const int MAX = 10005;int f[105], sg[MAX];void get_sg(int n){    memset(sg, 0, sizeof(sg));    bool vst[MAX];    for(int i = 0; i < MAX; i++)    {        memset(vst, false, sizeof(vst));        int h = 0, j;        while(i >= f[h] && h < n)            vst[sg[i - f[h++]]] = true;        for(j = 0; j <= i; j++)        {            if(!vst[j])            {                sg[i] = j;                 break;            }        }    }    return ;}int k;int m,I;int main(){    while(~scanf("%d", &k) && k )    {        for(int i=0;i<k;i++)        {            scanf("%d", &f[i]);        }        sort(f, f+k);        get_sg(k);        scanf("%d", &m);        for(int i=0;i<m;i++)        {            int heaps,ans=0;            scanf("%d", &I);            for(int j=0;j<I;j++)            {                scanf("%d", &heaps);                ans ^= sg[heaps];            }            if(!ans)              printf("L");            else              printf("W");        }        printf("\n");    }    return 0;}
0 0