博弈论 sg函数

来源:互联网 发布:三国杀 银两武将 知乎 编辑:程序博客网 时间:2024/05/24 04:13

http://baike.baidu.com/link?url=RvHq88XaFKNd0XJC97k2JWvIJSPZiLKvVhVnA_yCPR_K-cZhb2lLIjG3XHatW8VeyzLxbbOvYWqEtcc2RSdls_7mPQDbixegyJFRIBJFdj_

http://www.cnblogs.com/frog112111/p/3199073.html

两人操控一个棋子要从起点到终点,每次可以走若干步(看下边的三种规则),谁无路可走谁就输。

对于一个子游戏(之所以说是子游戏,是因为情况可能不止一个棋子,比如两人操作两个棋子。可以认为一个棋子是一个子游戏。而总游戏的胜利为各个子游戏的sg的异或)(sg[i]为0为必败点,不为0为必胜点)

三种规则

1.每次可以走任意步,那么sg[i] = i,

2.每次可以走1~m步,那么sg[i] = i%(m+1),

3对于不连续的步数。下面的函数。

#include<vector>#include<iostream>using namespace std;vector<int> sg(20);vector<int> f = {0,1,2,5};//每次可以走的步数,这里设为1,2,,5。f[0]无意义。std::vector<int> hash0(20);//找到mex({sg[当前步数减去可以走的步数}),最小非负整数void getsg(int n){for(int i=0; i<sg.size(); i++) sg[i] = 0;for(int i=1; i<=n; i++){for(int i=0; i<hash0.size(); i++) hash0[i] = 0;for(int j=1; f[j] <= i; j++){hash0[sg[i-f[j]]] = 1;}for(int j=0; j <=n; j++){if(hash0[j] == 0){sg[i] = j;break;}}cout<<i<<"  "<<sg[i]<<endl;} }  int main() { getsg(20); return 0;  } 

0 0