HDU 5724 Chess(SG函数 Nim博弈)

来源:互联网 发布:社会阶级 知乎 编辑:程序博客网 时间:2024/05/16 05:12

给定一个n*20的棋盘,在棋盘上有m个棋子,每个棋子的合法移动是当这个棋子右边没有棋子时,将这个棋子移动到右边一格,当右边有棋子时,到其右边下一个位置直到第一个空的位置。

因为棋子的移动只在行上,所以容易想到多堆的nim博弈。因为每行20个空格。所以刚好可以状压枚举所有情况的sg值。

刚开始不知道sg值的范围所以用的是set来保存,结果TLE,最后打表看了一下最大值只有20.。。

最后结果就是SG(1)^sg(2)..^sg(n)


#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <map>#include <stack>#include <queue>#include <string.h>#include <string>#include <iomanip>#include <cstring>#include <vector>#include <functional>#include <cmath>#include <sstream>#include <set>using namespace std;#define PI acos(-1.0)#define sp system("pause")typedef long long ll;typedef unsigned long long ull;const ll mod = 1000000007;#define PI acos(-1.0)int sg[(1 << 21) + 20];bool vis[21];void init(){memset(sg,0, sizeof sg);int len = 1 << 20;for (int i = 0; i < len;i++){memset(vis, false, sizeof vis);for (int j = 19; j >= 0;j--){if (i&(1 << j)){int k = j-1;while (k >= 0 && (i&(1 << k)) != 0)k--;if (k >= 0){int tmp = i;tmp ^= (1 << j);tmp ^= (1 << k);vis[sg[tmp]] = true;}}}for (int j = 0; j < len;j++)if (!vis[j]){sg[i] = j; break;}}}int main(){init();int T;cin >> T;while (T--){int n;int ans = 0;cin >> n;for (int i = 0; i < n; i++){int tmp=0;int m;scanf("%d", &m);for (int j = 0; j < m; j++){int x;scanf("%d", &x);x = 20 - x;tmp ^= (1 << x);}ans ^= sg[tmp];}if (ans)puts("YES");else puts("NO");}}




0 0
原创粉丝点击