标签:
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1944
http://acm.hdu.edu.cn/showproblem.php?pid=1536
1 #include<stdio.h> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 int s[105]; 7 int f[10005]; 8 int sizeS, T, n, num, sum; 9 int mex( int t ){ 10 bool g[105]; 11 memset(g,0,sizeof(g)); 12 int tmp; 13 for( int i = 0; i < sizeS; ++i){ 14 tmp = t - s[i]; 15 if( tmp < 0 ) 16 break; 17 if( f[tmp] == -1 ) 18 f[tmp] = mex(tmp); 19 g[f[tmp]] = 1; 20 } 21 for( int i = 0; i < 105; ++i) 22 if( g[i] == 0 ){ 23 return i; 24 } 25 } 26 int main() 27 { 28 while(~scanf("%d",&sizeS)&&sizeS){ 29 for( int i = 0; i < sizeS; ++i){ 30 scanf("%d",&s[i]); 31 }//读取数据 32 sort(s,s+sizeS); 33 memset(f,-1,sizeof(f)); 34 f[0] = 0; 35 scanf("%d",&T); 36 while(T--){ 37 scanf("%d", &n); 38 sum = 0; 39 while(n--){ 40 scanf("%d",&num); 41 if( f[num] == -1) 42 f[num] = mex(num); 43 sum = sum^f[num]; 44 } 45 if(!sum) 46 printf("L"); 47 else 48 printf("W"); 49 } 50 printf("\n"); 51 } 52 }
终于明白了SG函数是什么意思,应该算是博弈论入门了吧。。。
关于博弈论的相关资料:
博弈基础知识点:http://blog.csdn.net/acm_cxlove/article/details/7854530
hdoj 1536的题解:http://www.cnblogs.com/AdaByron/archive/2011/08/07/2200981.html
S-G函数的介绍:http://www.cnblogs.com/Knuth/archive/2009/09/05/1561007.html
下面简单小结一下这两天看博弈论的一些知识点:
(一)巴什博奕(Bash Game):只有一堆n个物品,两个人轮流从这堆物品中取物,
规定每次至少取一个,最多取m个。最后取光者得胜。
令 k = m + 1; 构成一对操作,第一个人无论取多少个,假设为x个,第二个人只需要取 k - x ,选择权又回到了第一个人;
将 n 分解: n = p * ( m + 1 ) + res; 第一个人只要在第一次取res个,剩下的所有回合取 k - x个,必能获胜。
当且仅当 res = 0 的情况下,第二个人才能获胜。
(二)威佐夫博奕(Wythoff Game):有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,
规定每次至少取一个,多者不限,最后取光者得胜。
存在一个很好玩的规律,定义(ak, bk)为局势,如果甲面对局势(ak, bk),甲已经输了,则称之为奇异局势,
奇异局势有以下三个性质:
1、任何自然数都包含在一个且仅有一个奇异局势中。
2、任意操作都可将奇异局势变为非奇异局势。
3、采用适当的方法,可以将非奇异局势变为奇异局势。
两个人如果都采用正确操作,那么面对非奇异局势,先拿者必胜;反之,则后拿者取胜。
ak =[k(1+√5)/2],bk= ak + k (k=0,1,2,…,n 方括号表示取整函数)
(三)尼姆博奕(Nimm Game):有三堆各若干个物品,两个人轮流从某一堆取任意多的物品,
规定每次至少取一个,多者不限,最后取光者得胜。
引入了异或运算,奇异局势的异或值为0,非奇异局势的异或值不为0;
非奇异局势转变为奇异局势,将一个数减少为其他数的奇异和,具体方式可参考1850题。
hdoj 1850:http://acm.hdu.edu.cn/showproblem.php?pid=1850
1 #include<stdio.h> 2 #include<string> 3 int main(){ 4 int N; 5 int num[105]; 6 int ans; 7 int cnt; 8 while(~scanf("%d",&N) && N ){ 9 cnt = ans = 0; 10 for( int i = 0; i < N; ++i){ 11 scanf("%d",&num[i]); 12 ans = ans ^ num[i]; 13 // printf("%d\n",ans); 14 } 15 if( ans == 0 ) 16 printf("0\n"); 17 else{ 18 for( int i = 0; i < N; ++i){ 19 int k = num[i]^ans; 20 if( k < num[i]) 21 cnt++; 22 } 23 printf("%d\n",cnt); 24 } 25 } 26 }
(四)S-G 函数(Sprague-Garundy):
首先定义mex ( minimal excludant ) 运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数。
例如mex{0,1,2,4}=3、mex{2,3,5}=0、mex{}=0。
定义关于图的每个顶点的 Sprague-Garundy 函数 g如下:g(x)=mex{ g(y) | y是x的后继 }
多棋子的有向图游戏的局面是P-position当且仅当所有棋子所在的位置的SG函数的异或为0。
标签:
原文地址:http://www.cnblogs.com/blueprintf/p/4715088.html