博弈-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 点击打开链接
- /*
- 收获:
- */
- #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\n",(double)clock()/CLOCKS_PER_SEC);
- }
/*收获:*/#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\n",(double)clock()/CLOCKS_PER_SEC);}
方法二:递归迭代
以下
- #include"iostream"
- #include"algorithm"
- #include"string.h"
- using namespace std;
- int s[101],sg[10001],k;
- int getsg(int m)
- {
- int hash[101]={0};
- int i;
- for(i=0;i<k;i++){
- if(m-s[i]<0)
- break;
- if(sg[m-s[i]]==-1)
- sg[m-s[i]]=getsg(m-s[i]);
- hash[sg[m-s[i]]]=1;
- }
- for(i=0;;i++)
- if(hash[i]==0)
- return i;
- }
- int main()
- {
- //int k;
- // freopen("game.in","r",stdin);
- //freopen("game.out","w",stdout);
- while(cin>>k,k)
- {
- int i;
- for(i=0;i<k;i++)
- cin>>s[i];
- sort(s,s+k);
- memset(sg,-1,sizeof(sg));
- sg[0]=0;
- int t;
- cin>>t;
- while(t--)
- {
- int n,m;
- cin>>n;
- int ans=0;
- while(n--)
- {
- cin>>m;
- if(sg[m]==-1)
- sg[m]=getsg(m);
- ans^=sg[m];
- }
- if(ans)
- cout<<'W';
- else cout<<'L';
- }
- cout<<endl;
- }
- return 0;
- }
#include"iostream"#include"algorithm"#include"string.h"using namespace std;int s[101],sg[10001],k;int getsg(int m){ int hash[101]={0}; int i; for(i=0;i<k;i++){ if(m-s[i]<0) break; if(sg[m-s[i]]==-1) sg[m-s[i]]=getsg(m-s[i]); hash[sg[m-s[i]]]=1; } for(i=0;;i++) if(hash[i]==0) return i; }int main(){ //int k; // freopen("game.in","r",stdin); //freopen("game.out","w",stdout); while(cin>>k,k) { int i; for(i=0;i<k;i++) cin>>s[i]; sort(s,s+k); memset(sg,-1,sizeof(sg)); sg[0]=0; int t; cin>>t; while(t--) { int n,m; cin>>n; int ans=0; while(n--) { cin>>m; if(sg[m]==-1) sg[m]=getsg(m); ans^=sg[m]; } if(ans) cout<<'W'; else cout<<'L'; } cout<<endl; } return 0;}
是别人的代码:
- 博弈-sg函数的原理和优化(hdu-1536)
- 博弈-sg函数的原理和优化(hdu-1536)
- HDU 1536 S-Nim (博弈 sg函数 Nim和)
- hdu 1536 博弈 SG函数(dfs)
- hdu 1536、hdu 1944 S-Nim(博弈SG函数)
- 博弈 hdu 1536 SG函数解法
- HDU 1536 S-Nim [SG函数]【博弈】
- HDU 1536 S-Nim 博弈,SG函数
- HDU 5724 Chess(博弈,SG函数)
- 博弈(SG函数 hdu 3032)
- sg函数 和 博弈
- HDU 1536 (博弈SG)
- hdu 1868 博弈 SG函数
- HDU 5724 博弈,SG函数
- HDU 1536(sg博弈) S-Nim
- HDU 1536 S-Nim(SG博弈)
- [博弈]SG函数的求法和一些结论 NIM博弈
- HDU 1536 && HDU 1944 S-Nim (Nim博弈、SG函数模板)
- ctags 、 cscope vim
- linux 下 /bin /sbin 的区别及重要目录
- JDBC数据库编程
- Access 2007 宝典--学习笔记3(查询)
- oracle dmp文件导入 与 blob图片导出
- 博弈-sg函数的原理和优化(hdu-1536)
- Android之列表对话框
- jQuery基础 -- 添加/移除CSS类
- Android 各版本的 support vx包相关笔记
- VoIP和电话网络浅析
- web.xml 中的listener、 filter、servlet 加载顺序
- ORACLE数据库性能优化之表的NOLOGGING
- jar命令小记
- java设计模式之代理模式(转自一淫才)