[置顶] 博弈(个人小结)

博弈(寻找必输点)
 1.SG函数
   
      函数值g(想)=mex{g(y)|y是想的后续状态}
      mex(s)表示s中没有出现的最小非负整数。        例:g(S1)=mes(g(s0))=mes(0)=1;
   SG值求解:
     2.可选步数为任意步,SG(x) = x;   
    
   3   可选步数为1-m的连续整数,直接取模即可,SG(x) = x % (m+1);  
      1. 可选步数不任意,如下:
 
  1. int g(int temp , int k) // temp是一个堆的数字,k为可选抽取规则s【】的个数  (参考HDU 1536)
  2. {    
  3.     int mex[101],i;    
  4.     memset(mex,0,sizeof(mex));    
  5.     if(sg[temp]!=-1) return sg[temp]; //集合S一致,则每个数量的mex一样,所以可以重复利用  
  6.     if(temp-s[0]<0) return sg[temp]=0; //s[0]为集合中最小值,temp-s[0]<0,则temp不可能到达其他状态,一定为P       
  7.     for(i=0;i<k && temp-s[i]>=0;i++)  //判断条件,因为s[]排了序,当temp-s[i]<0就停止循环。   
  8.     {     
  9.         mex[g(temp-s[i] , k)]=1;  //temp的后继SG函数中的没有出现的最小非负数       
  10.     }    
  11.     for(i=0;;i++) //通过temp的后继SG函数出现的非负数得temp的结果    
  12.     if(!mex[i])  return sg[temp]=i;    
  13. }    
2.BASH 博弈
  必败点s=k(m+1)
    ①m>=n,先手必胜
   ②n=k(m+1)+x (x<=m)先手必胜 ③n=k(m+1)先手必败
  判断代码:
    
  1. if(n%(m+1)||m>=n)  
  2.             printf("first\n");  
  3.         if(n%(m+1)==0)  
  4.             printf("second\n");
3.nim游戏
  a1^a2……^an=0(为P点或T点) (按位异或:相同为0,不同位1)
  T(异或和=0) S(疑惑和≠0)
  T2( 充裕堆>=2) T0( 充裕点=0)
   S0(奇数个孤独堆) S1,S2(充裕堆有1个或大于等于2个,gx!=0&&sum1!=0)
综上所述,必输态有:  T2,S0 
          必胜态:    S2,S1,T0.
  判断代码:
  1. if((ans!=0 && sum1!=0) || (ans==0) && sum1==0)  
  2.      printf("YES\n");  
  3. if((ans==0 && sum1>=2) || (ans!=0 && sum2%2!=0 && sum1==0)) printf("NO\n"); 



测试 数据 重定向
[cpp]  view plain copy print ?
  1. freopen("in.txt","r",stdin);  
  2.     freopen("out.txt","w",stdout); 

你可能感兴趣的:([置顶] 博弈(个人小结))