标签:style http color io for ar amp 算法 size
hdu1847 Good Luck in CET-4 Everybody!
题意:
总共n张牌,双方轮流抓牌,每人每次抓牌的个数只能是2的幂次(即:1,2,4,8,16…),抓完牌,胜负结果也出来了:最后抓完牌的人为胜者。给出n,问先手赢还是后手赢?
PS:当然这题可以直接推出 n%3==0必败,否则必胜。 //巴什博奕
下面介绍另外一种做法
SG值:一个点的SG值就是一个不等于它的后继点的SG的且大于等于零的最小整数。//同mex()函数
简单点来讲就是当前状态离最近一个必败点的距离。
SG(x)=mex{SG(S)}
S是x的后继状态的SG函数值集合,mex(S)表示不在S内的最小非负整数。
SG(x) = 0 当且仅当x为必败状态。
我们枚举下牌数为0-10的SG值:
num: 0 1 2 3 4 5 6 7 8 9 10
sg值:0 1 2 0 1 2 0 1 2 0 1
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1000 + 10;
int arr[11], sg[maxn];
void pre() { //把1000以内的所有的可能一次拿的牌都算出来!
arr[0] = 1;
for(int i=1; i<=10; ++i) arr[i] = arr[i-1]*2;
}
int mex(int x) { //这是求解该点的sg值的算法函数(采用记忆化搜索)
if(sg[x]!=-1) return sg[x];
bool vis[maxn];
memset(vis, false, sizeof vis );
for(int i=0; i<10; ++i) {
int temp = x - arr[i];
if(temp<0) break;
sg[temp] = mex(temp);
vis[sg[temp]] = true;
}
for(int i=0; ; ++i) {
if(!vis[i]) {
sg[x] = i;
break;
}
}
return sg[x];
}
int main() {
int n;
pre();
while(scanf("%d", &n)!=EOF) {
memset(sg, -1, sizeof sg );
if(mex(n)) printf("Kiki\n");
else printf("Cici\n");
}
return 0;
}hdu1847 Good Luck in CET-4 Everybody! ,巴什博奕,理解SG函数
标签:style http color io for ar amp 算法 size
原文地址:http://blog.csdn.net/yew1eb/article/details/38757811