POJ2960 S-Nim SG函数博弈

http://poj.org/problem?id=2960

/*
POJ 2960 S-Nim
大意:有n堆石子,每堆石子个数已知,两人轮流从中取石子,
每次可取的石子数x满足x属于集合S(k) = {s1,s2,s3...sk-1},问先拿者是否有必胜策略?


输入 knum 表示s数组的大小 输入knum个si 表示能一次拿的数量
输入 mnum 表示每次测试数据组数 对于每组 输入lnum表示一共的堆数
之后lnum个数 表示每堆的数量
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 100+10
int knum,mnum,lnum;
int ans[N],si[N],hi[N],sg[10010];
int cmp( const void *a , const void *b )
{
 return *(int *)a - *(int *)b;
}
int mex(int x)//求x的sg值(可作为模版应用)
{
 int i;
 if(sg[x]!=-1) return sg[x];
 bool vis[N];//注意要讲vis定义到函数里面!因为每次都要改变其值
 memset(vis,false,sizeof(vis));
 for(i=0;i<knum;i++)
 {
  int temp=x-si[i];
  if(temp<0) break;
  sg[temp]=mex(temp);
  vis[sg[temp]]=true;
 }
 for(i=0;;i++)
 {
  if(!vis[i])
  {
   sg[x]=i; break;
  }
 }
 return sg[x];
}

int main()
{
 int i,j;
 while(scanf("%d",&knum) && knum)
 {
  for(i=0;i<knum;i++)
   scanf("%d",&si[i]);
  qsort(si,knum,sizeof(si[0]),cmp);
  memset(sg,-1,sizeof(sg));
  sg[0]=0;
  memset(ans,0,sizeof(ans));
  scanf("%d",&mnum);
  for(i=0;i<mnum;i++)
  {
   scanf("%d",&lnum);
   for(j=0;j<lnum;j++)
   {
    scanf("%d",&hi[i]); ans[i]^=mex(hi[i]);//尼姆博弈
   }
  }
  for(i=0;i<mnum;i++)
  {
   if(ans[i]==0) printf("L");
   else printf("W");
  }
  printf("\n");
 }
 return 0;
}


v

 

 

求SG的值的方法  还有一个比较流行的方法是一个DFS的  感觉没有这个速度好


 

你可能感兴趣的:(POJ2960 S-Nim SG函数博弈)