标签:break void space 速度 ++ return 证明 总结 情况下
这里是看了学长的例会以及挑战上关于博弈的知识进行一下知识总结
定义:
必败点P:位于此位置的人,在双方操作均优的情况下,必败,记作“0”
必胜点N:位于此位置的人,在双方操作均优的情况下,必胜,记作“1”
性质:
游戏结束的点(通常为0点)均为必败点
必胜点等价于必有一种方式可以到达必败点
必败点等价于所能到的点全为必胜点
\(n\)个石子,A B两个人取,操作者必须取\(1\sim m\)个石子,先取完获胜
结论:必败点 \(n\%\left(m+1\right)=0\) ? 必胜点\(n\%\left(m+1\right)\ne0\)
证明:(假设\(m=2\))
n | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|---|
PN | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 0 |
一个其实用处不大的模板
博主实测,\(mex\)使用vis数组速度远快过set
int sg[maxn],f[maxn];
bool vis[maxn];
void get_sg()
{
memset(sg, 0, sizeof(sg));
for (int i = 1; i < maxn; ++i)
{
memset(vis,0,sizeof(vis));
for (int j = 0; j < N && f[j] <= i; ++j)
vis[sg[i - f[j]]];
for(int j=0;;++j)
if (!vis[j])
{
sg[i] = j;
break;
}
}
}
洛谷-P2197 Nim博弈:\(n\)堆石子,每堆有\(a[i]\)个,A B两人轮流取,每次可以在一堆石子中取任意个(可一次性取完)最后率先取完者获胜
结论:直接套用SG定理,可以发现每堆石子的\(sg\)值恰好为拥有石子的个数,再求异或和即可
HDU-2873 Bomb Game
结论:利用记忆化搜索求得SG值
#include<bits/stdc++.h>
using namespace std;
int sg[55][55];
int get_sg(int x, int y)
{
if (~sg[x][y])
return sg[x][y];
bool vis[3000] = {0};
if (x > 1 && y > 1)
{
for (int i = 1; i < x; ++i)
for (int j = 1; j < y; ++j)
vis[get_sg(i, y)^get_sg(x, j)]=true;
}
else if (y == 1 && x > 1)
for (int i = 1; i < x; ++i)
vis[get_sg(i, 1)]=true;
else if (x == 1 && y > 1)
for (int i = 1; i < y; ++i)
vis[get_sg(1, i)]=true;
for (int i = 0;; ++i)
if (vis[i] == false)
return sg[x][y] = i;
}
char s[55];
int main()
{
int n, m;
memset(sg, -1, sizeof(sg));
sg[1][1] = 0;
while (~scanf("%d%d", &n, &m) && n + m)
{
int ans = 0;
for (int i = 1; i <= n; ++i)
{
scanf("%s", s + 1);
for (int j = 1; j <= m; ++j)
if (s[j] == ‘#‘)
ans ^= get_sg(i, j);
}
printf("%s\n", ans ? "John" : "Jack");
}
}
标签:break void space 速度 ++ return 证明 总结 情况下
原文地址:https://www.cnblogs.com/DreamW1ngs/p/13912492.html