博弈论
Bash
#define _MAX 10000
int a[_MAX];
int b[_MAX];
int bash(int N, int K)
{
if (N % (K + 1) == 0)
{
return 2;
}
return 1;
}
int main()
{
int T;
scanf("%d", &T);
for (int i = 0; i < T; i++)
{
scanf("%d%d", a + i, b + i);
}
for (int i = 0; i < T; i++)
{
if (bash(a[i], b[i]) == 1)
{
printf("A\n");
}
else
{
printf("B\n");
}
}
return 0;
}
Nim
int main(int argc, const char * argv[])
{
int N, stone, tag = 0;
scanf("%d", &N);
while (N--)
{
scanf("%d", &stone);
tag ^= stone;
}
//tag为0则为后手赢,否则为先手赢
printf("%c\n", tag == 0 ? 'B' : 'A');
return 0;
}
SG函数
SG打表
const int MAX_DIG = 64;
// SG打表
// f[]:可以取走的石子个数
// sg[]:0~n的SG函数值
// hash[]:mex{}
int f[MAX_DIG];
int sg[MAX_DIG];
int hash[MAX_DIG];
void getSG(int n)
{
memset(sg, 0, sizeof(sg));
for (int i = 1; i <= n; i++)
{
memset(hash, 0, sizeof(hash));
for (int j = 1; f[j] <= i; j++)
{
hash[sg[i - f[j]]] = 1;
}
for (int j = 0; j <= n; j++) // 求mes{}中未出现的最小的非负整数
{
if (hash[j] == 0)
{
sg[i] = j;
break;
}
}
}
}
SG DFS
const int MAX_DIG = 64;
// DFS
// 注意 S数组要按从小到大排序 SG函数要初始化为-1 对于每个集合只需初始化1遍
// n是集合s的大小 S[i]是定义的特殊取法规则的数组
int s[MAX_DIG];
int sg[MAX_DIG * 100];
int n;
int SG_dfs(int x)
{
if (sg[x] != -1)
{
return sg[x];
}
bool vis[MAX_DIG];
memset(vis, 0, sizeof(vis));
for (int i = 0; i < n; i++)
{
if (x >= s[i])
{
SG_dfs(x - s[i]);
vis[sg[x - s[i]]] = 1;
}
}
int e;
for (int i = 0; ; i++)
{
if (!vis[i])
{
e = i;
break;
}
}
return sg[x] = e;
}
Wythoff
int main()
{
int t, a, b, m, k;
scanf("%d", &t);
while (t--)
{
scanf("%d%d", &a, &b);
if (a > b)
{
a ^= b;
b ^= a;
a ^= b;
}
m = b - a;
k = (int)(m * (1 + sqrt(5)) / 2.0);
//m = ? * a
//k = m / ?
//?:黄金分割数
//如果a == k,则为后手赢,否则先手赢(奇异局)
printf("%s\n", a == k ? "B" : "A");
}
return 0;
}
应用示例
51Nod 1066 Bash游戏
51Nod 1069 Nim游戏
51Nod 1072 威佐夫游戏
51Nod 1185 威佐夫游戏 V2
51Nod 1714 B君的游戏