*模板--博弈
?
?
1 //SG函數打表 2 const int MAX_DIG = 64; 3 4 // SG打表 5 // f[]:可以取走的石子個數 6 // sg[]:0~n的SG函數值 7 // hash[]:mex{} 8 int f[MAX_DIG]; 9 int sg[MAX_DIG]; 10 int hash[MAX_DIG]; 11 12 void getSG(int n) 13 { 14 memset(sg, 0, sizeof(sg)); 15 for (int i = 1; i <= n; i++) 16 { 17 memset(hash, 0, sizeof(hash)); 18 for (int j = 1; f[j] <= i; j++) 19 { 20 hash[sg[i - f[j]]] = 1; 21 } 22 for (int j = 0; j <= n; j++) // 求mes{}中未出現的最小的非負整數 23 { 24 if (hash[j] == 0) 25 { 26 sg[i] = j; 27 break; 28 } 29 } 30 } 31 } 32 33 //SG DFS 34 const int MAX_DIG = 64; 35 36 // DFS 37 // 注意 S數組要按從小到大排序 SG函數要初始化為-1 對于每個集合只需初始化1遍 38 // n是集合s的大小 S[i]是定義的特殊取法規則的數組 39 int s[MAX_DIG]; 40 int sg[MAX_DIG * 100]; 41 int n; 42 43 int SG_dfs(int x) 44 { 45 if (sg[x] != -1) 46 { 47 return sg[x]; 48 } 49 bool vis[MAX_DIG]; 50 memset(vis, 0, sizeof(vis)); 51 for (int i = 0; i < n; i++) 52 { 53 if (x >= s[i]) 54 { 55 SG_dfs(x - s[i]); 56 vis[sg[x - s[i]]] = 1; 57 } 58 } 59 int e; 60 for (int i = 0; ; i++) 61 { 62 if (!vis[i]) 63 { 64 e = i; 65 break; 66 } 67 } 68 return sg[x] = e; 69 } 70 71 72 //BASH博弈 73 //巴什博奕:只有一堆n個物品,兩個人輪流從中取物,規定每次最少取一個,最多取m個,最后取光者為勝。 74 #include <iostream> 75 using namespace std; 76 int main() 77 { 78 int n,m; 79 while(cin>>n>>m) 80 if(n%(m+1)==0) cout<<"后手必勝"<<endl; 81 else cout<<"先手必勝"<<endl; 82 return 0; 83 } 84 85 //威佐夫博弈(Wythoff Game): 86 //有兩堆各若干的物品,兩人輪流從其中一堆取至少一件物品,至多不限,或從兩堆中同時取相同件物品,規定最后取完者勝利。 87 //直接說結論了,若兩堆物品的初始值為(x,y),且x<y,則另z=y-x; 88 //記w=(int)[((sqrt(5)+1)/2)*z ]; 89 //若w=x,則先手必敗,否則先手必勝。 90 91 /* 92 尼姆博弈(Nimm Game): 93 尼姆博弈指的是這樣一個博弈游戲:有任意堆物品,每堆物品的個數是任意的,雙方輪流從中取物品,每一次只能從一堆物品中取部分或全部物品,最少取一件,取到最后一件物品的人獲勝。 94 結論就是:把每堆物品數全部異或起來,如果得到的值為0,那么先手必敗,否則先手必勝。 95 */ 96 97 /* 98 斐波那契博弈: 99 有一堆物品,兩人輪流取物品,先手最少取一個,至多無上限,但不能把物品取完,之后每次取的物品數不能超過上一次取的物品數的二倍且至少為一件,取走最后一件物品的人獲勝。 100 結論是:先手勝當且僅當n不是斐波那契數(n為物品總數) 101 */ View Code?
轉載于:https://www.cnblogs.com/yijiull/p/7726261.html
總結
- 上一篇: 解方程 2014NOIP提高组 (数学)
- 下一篇: 洛谷 P1598 垂直柱状图【字符串】