2010年02月05日.sgu153 经典博弈问题 substration game
sgu153:这个问题是经典的博弈论教程<<GAME THEORY>> Thomas S. Ferguson,
1.4 Subtraction Games 中有详细介绍,就是状态的逆推。
此书在
http://www.math.ucla.edu/~tom/Game_Theory/Contents.html
上有下载,是作者写的免费电子书。
本题的关键就是找出循环节,然后将n %= len;
进而求出最终的状态。
下面代码很挫,基本属于暴力。
1
2 const int N = 1024;
3 int stat[N];
4 int p[N],m,n;
5
6 bool find(int x)
7 {
8 int i;
9 for (i = 0;i <= m;i++) {
10 if (x - p[i] >= 0 && stat[x-p[i]] == 0) {
11 return true;
12 }
13 }
14 return false;
15 }
16
17 bool repeat(int mod,int offset,int depth)
18 {
19 if (depth == 0) {
20 return true;
21 }
22 int i;
23 for (i = 0;i < mod;i++) {
24 if (stat[i+offset] != stat[i+mod+offset]) {
25 return false;
26 }
27 }
28 return repeat(mod,offset + mod,depth-1);
29 }
30
31 int main()
32 {
33 int i,j,k,testcase,mod = 2;
34 stat[0] = 1, stat[1] = 0, p[0] = 1;
35 scanf("%d",&testcase);
36 while (testcase--) {
37 scanf("%d%d",&n,&m);
38 for (i = 1;i <= m;i++) { scanf("%d",p + i); }
39
40 sort(p,p+m+1);
41 for (i = 2;i <= 1024;i++) {
42 if (find(i)) {
43 stat[i] = 1;
44 }
45 }
46
47 for (i = 2;i <= 20;i++) {
48 if (repeat(i,0,10)) {
49 mod = i;
50 }
51 }
52
53 if (stat[n % mod]) {
54 puts("FIRST PLAYER MUST WIN");
55 }else {
56 puts("SECOND PLAYER MUST WIN");
57 }
58 }
59 return 0;
60 }
61