SRM 624 D2L3: GameOfSegments, 博弈论,Sprague–Grundy theorem,Nimber
2014-08-15 00:39
701 查看
题目:http://community.topcoder.com/stat?c=problem_statement&pm=13204&rd=15857
这道题目需要用到博弈论中的经典理论,Sprague–Grundy theorem,下面将相关理论做一个总结:
Impartial Game:公平游戏,双方除了谁先开始游戏外,其余都相同。
Nim:一类经典的Impartial Game,很多游戏都可以等价于Nim。
Nimber(Grundy numbers):可以理解为标识一个游戏状态的数。在游戏进行过程种,每个状态都应一个唯一的Nimber。
Sprague-Grundy定理:对一个 Impartial Game 的状态,其等效游戏的 Nimber 数,就等于所有其后继状态 Nimber 数的 Mex 函数值。
Mex:对一个集合S,若G为S的补集,则 Mex{S} = min {G}。
根据 Sprague-Grundy定理,要求当前游戏状态的Nimber数,则需要求出其所有后继状态的Nimbers,然后对这些Nimbers取Mex值。而且当存在多个“子Impartial
Game”同时进行时,这一定理尤其有用,对每个“子游戏”状态的Nimber数进行异或操作,就是该状态的Nimber数。
代码如下:
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <bitset>
#include <string>
#include <vector>
#include <stack>
#include <deque>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <cstring>
#include <ctime>
#include <climits>
using namespace std;
#define CHECKTIME() printf("%.2lf\n", (double)clock() / CLOCKS_PER_SEC)
typedef pair<int, int> pii;
typedef long long llong;
typedef pair<llong, llong> pll;
#define mkp make_pair
#define FOREACH(it, X) for(__typeof((X).begin()) it = (X).begin(); it != (X).end(); ++it)
/*************** Program Begin **********************/
class GameOfSegments {
public:
int winner(int N) {
int Nimbers[1001];
Nimbers[0] = Nimbers[1] = 0;
for (int i = 2; i <= N; i++) {
set <int> options;
for (int j = 0; j <= i - 2; j++) {
options.insert(Nimbers[j] ^ Nimbers[i - j - 2]);
}
int r = 0;
while (options.count(r)) {
++r;
}
Nimbers[i] = r;
}
return (Nimbers
> 0 ? 1 : 2);
}
};
/************** Program End ************************/
参考:
http://www.cnblogs.com/fishball/archive/2013/01/19/2866311.html
http://www.cnblogs.com/hsqdboke/archive/2012/04/20/2459796.html
http://www.cnblogs.com/hsqdboke/archive/2012/04/21/2461034.html
这道题目需要用到博弈论中的经典理论,Sprague–Grundy theorem,下面将相关理论做一个总结:
Impartial Game:公平游戏,双方除了谁先开始游戏外,其余都相同。
Nim:一类经典的Impartial Game,很多游戏都可以等价于Nim。
Nimber(Grundy numbers):可以理解为标识一个游戏状态的数。在游戏进行过程种,每个状态都应一个唯一的Nimber。
Sprague-Grundy定理:对一个 Impartial Game 的状态,其等效游戏的 Nimber 数,就等于所有其后继状态 Nimber 数的 Mex 函数值。
Mex:对一个集合S,若G为S的补集,则 Mex{S} = min {G}。
根据 Sprague-Grundy定理,要求当前游戏状态的Nimber数,则需要求出其所有后继状态的Nimbers,然后对这些Nimbers取Mex值。而且当存在多个“子Impartial
Game”同时进行时,这一定理尤其有用,对每个“子游戏”状态的Nimber数进行异或操作,就是该状态的Nimber数。
代码如下:
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <bitset>
#include <string>
#include <vector>
#include <stack>
#include <deque>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <cstring>
#include <ctime>
#include <climits>
using namespace std;
#define CHECKTIME() printf("%.2lf\n", (double)clock() / CLOCKS_PER_SEC)
typedef pair<int, int> pii;
typedef long long llong;
typedef pair<llong, llong> pll;
#define mkp make_pair
#define FOREACH(it, X) for(__typeof((X).begin()) it = (X).begin(); it != (X).end(); ++it)
/*************** Program Begin **********************/
class GameOfSegments {
public:
int winner(int N) {
int Nimbers[1001];
Nimbers[0] = Nimbers[1] = 0;
for (int i = 2; i <= N; i++) {
set <int> options;
for (int j = 0; j <= i - 2; j++) {
options.insert(Nimbers[j] ^ Nimbers[i - j - 2]);
}
int r = 0;
while (options.count(r)) {
++r;
}
Nimbers[i] = r;
}
return (Nimbers
> 0 ? 1 : 2);
}
};
/************** Program End ************************/
参考:
http://www.cnblogs.com/fishball/archive/2013/01/19/2866311.html
http://www.cnblogs.com/hsqdboke/archive/2012/04/20/2459796.html
http://www.cnblogs.com/hsqdboke/archive/2012/04/21/2461034.html
相关文章推荐
- SRM 624 D2L3: GameOfSegments, 博弈论,Sprague–Grundy theorem,Nimber
- 博弈论重要算法:Sprague-Grundy 定理 (SRM 561 Div1 550)
- SRM 591 D2L3:YetAnotherTwoTeamsProblem,dp
- topcoder SRM 624 DIV2 CostOfDancing
- [转]博弈论(二):Sprague-Grundy函数
- topcoder SRM 624 DIV2 BuildingHeightsEasy
- SRM 624 Building Heights DivI 解读
- 博弈论(二):Sprague-Grundy函数
- SRM 599 D2L3: SimilarNames2,dp
- SRM 609 D2L3: VocaloidsAndSongs,dp
- SRM 620 D2L3: RandomGraph, dp
- 博弈论 Sprague-Grundy函数 ——转
- SRM 622 D2L3: Subsets, math, backtrack
- Sprague-Grundy Function-SG函数--博弈论(3)
- [leetcode flip game ii]sprague–grundy theorem
- 博弈论(二):Sprague-Grundy函数
- SRM 610 D2L3:MiningGoldEasy,dp
- SRM 510 D2L3:TheLuckyBasesDivTwo,brute force,optimization
- SRM 626 D2L3:NegativeGraphDiv2,构造新图
- SRM 615 D2L3:MergeStrings,dp