zoukankan      html  css  js  c++  java
  • 博弈——sg函数的原理和优化

    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  

    /* 

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

    方法二:递归迭代

    以下

    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. }  
  • 相关阅读:
    Linux内存运维操作及常用命令
    Quartz定时任务
    Spark DataSource Option 参数
    Hadoop HDFS命令
    Java,Scala:JDBCUtil,MySqlUtil,PhoenixJDBC
    RedisUtil,Redis工具类
    通过脚本本地下载Jar包
    Redis五种数据类型-设置key的过期时间
    spark整合Phoenix相关案例
    Spark Dataset DataFrame空值null,NaN判断和处理
  • 原文地址:https://www.cnblogs.com/lxm940130740/p/3268631.html
Copyright © 2011-2022 走看看