Paint Chain(博弈论-sg函数)
judge:HDUOJ 3980
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
source:2011 Multi-University Training Contest 14 - Host by FZU
Problem Description
Aekdycoin and abcdxyzk are playing a game. They get a circle chain with some beads. Initially none of the beads is painted. They take turns to paint the chain. In Each turn one player
HDUOJ 3980
Input
Output
Sample Input
2
3 1
4 2
Sample Output
Case #1: aekdycoin
Case #2: abcdxyzk
题意
有一串项链,项链上有n个珠子。现规定两个人每回合都必须拿走连续的m个珠子,最后不能拿走m个连续珠子的人输。给你n和m,问你谁会赢。
sg函数打表,博弈论没什么好解释的,也解释不清……
参考别人的解释:
一个圆环N个数,每次每个人只能给连续的M个数抹漆,最后不能抹的就算输(大概这个意思啦,英语不好)。。首先第一个人抹了之后就变成直线了。。先手变后手了…
(5,2) +++++之后的状态可以有<–+++><+–++><++–+><+++–>
一个问题的结果是其子问题的结果的亦或。。。
对于一个直线的情况,其子状态有前边空几个那么多的情况。。
比如(5,2) +++++,
当前边空0个时子游戏为(0,2)(3,2)
当前边空1个时子游戏有(1,2)(2,2)
当前边空2个时子游戏有(2,2)(1,2)
当前边空3个时子游戏有(3,2)(0,2)
所以求SG时记忆化递推。。就可以求出(n,m)状态的SG。
————————————————
版权声明:本文为CSDN博主「xtulollipop」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xtulollipop/article/details/51998133
代码
#include <string>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int N = 1e3+5;
const int mod = 1e9+7;
const int maxn = 10005;
int sg[1006];
int vis[1006];
int n, m;
int getsg(int n) {
if(sg[n] != -1) return sg[n];
if(n < m) return sg[n] = 0;
memset(vis, 0, sizeof(vis));
for(int i = m; i <= n; i++){
vis[getsg(i - m) ^ getsg(n - i)] = 1;
}
int pos = 0;
while(vis[pos]) pos++;
sg[n] = pos;
return pos;
}
int main() {
//freopen("in.txt", "r", stdin);
int T, ca = 1;
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
if(n < m) {
printf("Case #%d: abcdxyzk\n", ca++);
continue;
}
n -= m;
memset(sg, -1, sizeof(sg));
for(int i = 0; i <= n; i++) sg[i] = getsg(i);
printf("Case #%d: %s\n", ca++, !sg[n] ? "aekdycoin" : "abcdxyzk");
}
return 0;
}