博弈-sg函数的原理和优化(hdu-1536)

来源:互联网 发布:3.35 魔兽数据库 编辑:程序博客网 时间:2024/05/22 06:29
sg函数:sg函数是博弈中的确定一个position性质的一个函数,全称是sprague-grundy。

性质1:对于所有的p-position,都有sg = 0;对于所有的n-position都有sg != 0;

性质2:某点a的sg函数的值由它的后继的sg函数的值来决定,设后继为b, c, d, e……则sg(a) = mex(sg(a), sg(b), sg(c), sg(d), sg(e),……)

mex是不属于这个集合的最小非负整数。

应用范围:在此无环图中谁无法再次移动,便是输。(如果谁无法移动,便是赢,暂时不知如何解决。)

应用:通过判断该点,sg = 0是p点,sg != 0是N点。

构造sg函数的方法:

方法一:打表

例题:hdu-1536-S-nim 点击打开链接


[cpp] view plaincopyprint?
  1. /* 
  2. 收获: 
  3. */  
  4. #include<iostream>   
  5. #include<cstdlib>   
  6. #include<vector>   
  7. #include<map>   
  8. #include<cstring>   
  9. #include<set>   
  10. #include<string>   
  11. #include<algorithm>   
  12. #include<sstream>   
  13. #include<ctype.h>   
  14. #include<fstream>   
  15. #include<string.h>   
  16. #include<stdio.h>   
  17. #include<math.h>   
  18. #include<stack>   
  19. #include<queue>   
  20. #include<ctime>   
  21. //#include<conio.h>   
  22. using namespace std;  
  23.   
  24. const int INF_MAX=0x7FFFFFFF;  
  25. const int INF_MIN=-(1<<31);  
  26.   
  27. const double eps=1e-10;  
  28. const double pi=acos(-1.0);  
  29.   
  30. #define pb push_back   //a.pb( )   
  31. #define chmin(a,b) ((a)<(b)?(a):(b))  
  32. #define chmax(a,b) ((a)>(b)?(a):(b))   
  33.   
  34.   
  35. template<class T> inline T gcd(T a,T b)//NOTES:gcd(  
  36.   {if(a<0)return gcd(-a,b);if(b<0)return gcd(a,-b);return (b==0)?a:gcd(b,a%b);}  
  37. template<class T> inline T lcm(T a,T b)//NOTES:lcm(  
  38.   {if(a<0)return lcm(-a,b);if(b<0)return lcm(a,-b);return a*(b/gcd(a,b));}  
  39.   
  40.   
  41. typedef pair<intint> PII;  
  42. typedef vector<PII> VPII;  
  43. typedef vector<int> VI;  
  44. typedef vector<VI> VVI;  
  45. typedef long long LL;  
  46. int dir_4[4][2]={{0,1},{-1,0},{0,-1},{1,0}};  
  47. int dir_8[8][2]={{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1}};  
  48. //下,左下,左,左上,上,右上,右,右下。   
  49.   
  50. //******* WATER ****************************************************************  
  51.   
  52.   
  53. const int MAXN = 10500;  
  54. bool judge[150];  
  55. int sg[MAXN];  
  56. int M[150];  
  57. const int Init = 1e7;  
  58. int Num;  
  59.   
  60. void input_m()  
  61. {  
  62.     for(int i = 0; i < Num; i++)  
  63.     {  
  64.         cin>>M[i];  
  65.     }  
  66.     return ;  
  67. }  
  68.   
  69. void debug()  
  70. {  
  71.     cout<<"sg function"<<endl;  
  72.     for(int i = 0; i < 100; i++)  
  73.     {  
  74.         cout<<i<<" "<<sg[i]<<endl;  
  75.     }  
  76.     return ;  
  77. }  
  78.   
  79. void getsg()  
  80. {  
  81.     for(int i = 0; i < MAXN; i++)  
  82.     {  
  83.         memset(judge, falsesizeof(judge));  
  84.         //int tsg = Init;   
  85.         for(int j = 0; j < Num; j++)  
  86.         {  
  87.             int ps = i - M[j];  
  88.             if(ps >= 0) judge[sg[ps]] = true;  
  89.         }  
  90.         //if(tsg == Init) tsg = 0;   
  91.         for(int j = 0; j < Num + 1; j++)  
  92.         {  
  93.             if(judge[j] == false)  
  94.             {  
  95.                 sg[i] = j;  
  96.                 break;  
  97.             }  
  98.         }  
  99.     }  
  100.     //debug();   
  101.     return ;  
  102. }  
  103. int main()  
  104. {  
  105.     //freopen("input.txt","r",stdin);  
  106.     //freopen("output.txt","w",stdout);   
  107.     while(cin>>Num, Num)  
  108.     {  
  109.         input_m();  
  110.         getsg();  
  111.         int num;  
  112.         cin>>num;  
  113.         while(num--)  
  114.         {  
  115.             int nn, tp;  
  116.             cin>>nn;  
  117.             int ret = 0;  
  118.             for(int i = 0; i < nn; i++)  
  119.             {  
  120.                 cin>>tp;  
  121.                 ret ^= sg[tp];  
  122.             }  
  123.             if(ret == 0) cout<<"L";  
  124.             else cout<<"W";  
  125.         }  
  126.         cout<<endl;  
  127.     }  
  128.     return 0;  
  129.     //printf("%.6f\n",(double)clock()/CLOCKS_PER_SEC);  
  130. }  

方法二:递归迭代

以下

[cpp] view plaincopyprint?
  1. #include"iostream"   
  2. #include"algorithm"   
  3. #include"string.h"   
  4. using namespace std;  
  5. int s[101],sg[10001],k;  
  6. int getsg(int m)  
  7. {  
  8.     int hash[101]={0};  
  9.     int i;  
  10.     for(i=0;i<k;i++){  
  11.         if(m-s[i]<0)  
  12.             break;  
  13.         if(sg[m-s[i]]==-1)  
  14.             sg[m-s[i]]=getsg(m-s[i]);  
  15.         hash[sg[m-s[i]]]=1;  
  16.     }  
  17.     for(i=0;;i++)  
  18.         if(hash[i]==0)  
  19.             return i;  
  20.    
  21.    
  22. }  
  23. int main()  
  24. {  
  25.     //int k;   
  26.    // freopen("game.in","r",stdin);   
  27.     //freopen("game.out","w",stdout);  
  28.     while(cin>>k,k)  
  29.     {  
  30.         int i;  
  31.         for(i=0;i<k;i++)  
  32.             cin>>s[i];  
  33.         sort(s,s+k);  
  34.         memset(sg,-1,sizeof(sg));  
  35.         sg[0]=0;  
  36.         int t;  
  37.         cin>>t;      
  38.         while(t--)  
  39.         {  
  40.                
  41.             int n,m;  
  42.             cin>>n;  
  43.             int ans=0;  
  44.             while(n--)  
  45.             {  
  46.                 cin>>m;  
  47.                 if(sg[m]==-1)  
  48.                     sg[m]=getsg(m);  
  49.                 ans^=sg[m];  
  50.             }  
  51.             if(ans)  
  52.                 cout<<'W';  
  53.             else cout<<'L';  
  54.         }  
  55.         cout<<endl;  
  56.     }  
  57.     return 0;  
  58. }  

是别人的代码:
原创粉丝点击