hdu 1536 NIM博弈 (模板)

推荐文章

博弈论初步:http://www.cnblogs.com/Knuth/archive/2009/09/05/1561002.html

博弈解决思想:http://www.cnblogs.com/Knuth/archive/2009/09/05/1561005.html

NIM游戏:http://www.cnblogs.com/Knuth/archive/2009/09/05/1561008.html

关于SG函数:http://www.cnblogs.com/Knuth/archive/2009/09/05/1561007.html

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<string>
 6 #include<queue>
 7 #include<algorithm>
 8 #include<map>
 9 #include<iomanip>
10 #include<climits>
11 #include<string.h>
12 #include<stdlib.h>
13 #define INF 1e11
14 #define MAXN 60
15 using namespace std;
16
17 int k, a[100], f[10001];
18 int mex(int p)
19 {
20     int i, t;
21     bool g[101] = { 0 };
22     for (i = 0; i<k; i++)
23     {
24         t = p - a[i];
25         if (t<0)    break;
26         if (f[t] == -1)
27             f[t] = mex(t);
28         g[f[t]] = 1;
29     }
30     for (i = 0;; i++)
31     {
32         if (!g[i])
33             return i;
34     }
35 }
36
37 int main()
38 {
39     int n, i, m, t, s;
40     while (scanf("%d", &k), k) {
41         for (i = 0; i<k; i++)
42             scanf("%d", &a[i]);
43         sort(a, a + k);
44         memset(f, -1, sizeof(f));
45         f[0] = 0;
46         scanf("%d", &n);
47         while (n--){
48             scanf("%d", &m);
49             s = 0;
50             while (m--) {
51                 scanf("%d", &t);
52                 if (f[t] == -1)  f[t] = mex(t);
53                 s = s^f[t];
54             }
55             if (s == 0)
56                 printf("L");
57             else
58                 printf("W");
59         }
60         printf("\n");
61     }
62     return 0;
63 }

递归版

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<string>
 6 #include<queue>
 7 #include<algorithm>
 8 #include<map>
 9 #include<iomanip>
10 #include<climits>
11 #include<string.h>
12 #include<stdlib.h>
13 #define INF 1e11
14 #define MAXN 60
15 using namespace std;
16
17
18
19 int sg[10010];
20 int k, knum[110];
21 int flag[110];
22
23
24 int met(int n)
25 {
26     int i, ans = 0;
27     memset(flag, 0, sizeof(flag));
28     for (i = 0; i < k; i++)
29         if (n - knum[i] >= 0)
30             flag[sg[n - knum[i]]] = 1;
31     for (i = 0; i <= 101; i++)
32         if (flag[i] == 0) return i;
33 }
34
35
36 void Sprague_Grundy()
37 {
38     int i;
39     for (i = 1; i <= 10000; i++)
40         sg[i] = met(i);
41 }
42
43
44 int main()
45 {
46     int i, n, l, num, ans;
47     while (~scanf("%d", &k) && k)
48     {
49         for (i = 0; i < k; i++)
50             scanf("%d", &knum[i]);
51         Sprague_Grundy();
52         scanf("%d", &n);
53         while (n--)
54         {
55             ans = 0;
56             scanf("%d", &l);
57             while (l--)
58             {
59                 scanf("%d", &num);
60                 ans ^= sg[num];
61             }
62             printf(ans == 0 ? "L" : "W");
63         }
64         printf("\n");
65     }
66     return 0;
67 }

循环版

时间: 2024-09-28 20:33:23

hdu 1536 NIM博弈 (模板)的相关文章

HDU 1536 sg-NIM博弈类

题意:每次可以选择n种操作,玩m次,问谁必胜.c堆,每堆数量告诉. 题意:sg—NIM系列博弈模板题 把每堆看成一个点,求该点的sg值,异或每堆sg值. 将多维转化成一维,性质与原始NIM博弈一样. 1 // #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #

HDU 1907 Nim博弈变形

1.HDU 1907 2.题意:n堆糖,两人轮流,每次从任意一堆中至少取一个,最后取光者输. 3.总结:有点变形的Nim,还是不太明白,盗用一下学长的分析吧 传送门 分析:经典的Nim博弈的一点变形.设糖果数为1的叫孤独堆,糖果数大于1的叫充裕堆,设状态S0:a1^a2^..an!=0&&充裕堆=0,则先手必败(奇数个为1的堆,先手必败).S1:充裕堆=1,则先手必胜(若剩下的n-1个孤独堆个数为奇数个,那么将那个充裕堆全部拿掉,否则将那个充裕堆拿得只剩一个,这样的话先手必胜).T0:a1

hdu 5011 (nim博弈模版)

//nim博弈 //有n堆石头,两人轮流每次从一堆中拿至少1,之多全部的石头,没有石头可拿为lose //判断先手是win还是lose # include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int main() { int n,i; __int64 a,sum; while(~scanf("%d",&n)) { sum=0; fo

hdu 1907(Nim博弈)

John Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 4407    Accepted Submission(s): 2520 Problem Description Little John is playing very funny game with his younger brother. There is one big bo

hdu 1730 Nim博弈

Tom和Jerry正在玩一种Northcott游戏,可是Tom老是输,因此他怀疑这个游戏是不是有某种必胜策略,郁闷的Tom现在向你求救了,你能帮帮他么? 游戏规则是这样的:  如图所示,游戏在一个n行m列(1 ≤ n ≤ 1000且2 ≤ m ≤ 100)的棋盘上进行,每行有一个黑子(黑方)和一个白子(白方).执黑的一方先行,每次玩家可以移动己方的任何一枚棋子到同一行的任何一个空格上,当然这过程中不许越过该行的敌方棋子.双方轮流移动,直到某一方无法行动为止,移动最后一步的玩家获胜.Tom总是先下

HDU 1536——S-nim博弈

题目: Description Arthur and his sister Caroll have been playing a game called Nim for some time now. Nim is played as follows: The starting position has a number of heaps, all containing some, not necessarily equal, number of beads. The players take t

HDU 3032 (Nim博弈变形) Nim or not Nim?

博弈的题目,打表找规律还是相当有用的一个技巧. 这个游戏在原始的Nim游戏基础上又新加了一个操作,就是游戏者可以将一堆分成两堆. 这个SG函数值是多少并不明显,还是用记忆花搜索的方式打个表,规律就相当显然了. 1 #include <cstdio> 2 #include <cstring> 3 4 const int maxn = 100; 5 int sg[maxn * 2]; 6 bool vis[maxn * 2]; 7 8 int mex(int v) 9 { 10 if(

HDU 1850 (Nim博弈 取胜方案数) Being a Good Boy in Spring Festival

考虑到Bouton定理的证明过程,设n个数的Nim和(异或和)为X,其最高位的1在第k位,那么n个数中一定有个y的第k为也是个1. 将y的数量变为X xor y,那么n的数的Nim和为0,便转为先手必败局面. 所以先手有多少种取法,就看n个数里面有多少个y,满足二进制的第k为是个1. 1 #include <cstdio> 2 3 const int maxh = 20; 4 const int maxn = 100 + 10; 5 int a[maxn]; 6 7 int main() 8

HDU 2509 Nim博弈

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2509 题意:有N堆,谁最后拿谁输. 关键:判断孤单堆. 1 #include<cstdio> 2 #define ll long long 3 using namespace std; 4 5 int main() 6 { 7 int n; 8 while( ~scanf("%d",&n)){ 9 int temp,ans=0,flag=0; 10 for(int i=