题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1847
一堆牌一次只能取2的次幂张,谁取完谁赢。
巴什博弈的变形,但是我没看出来...
可以发现3和3的倍数一定没有办法一次取完,所以只要每次给对手留3或者3的倍数张就行了,又任意数只要减去1或者减去2都能变成3的倍数,而1和2都是可行的取法,所以只要开局不是3或者3的倍数,那么先手一定赢。
另外也可以用SG函数做,SG函数练手题。
找规律:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
int n;
while(~scanf("%d", &n)) {
if(n % 3 == 0) puts("Cici");
else puts("Kiki");
}
return 0;
}
SG函数:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int op[10], sg[1010], vis[1010];
void getsg() {
int i, j;
for(i = 0; i <= 9; i++) op[i] = (1 << i); //合法的取的个数
for(i = 1; i < 1001; i++) { //打表求sg值 ,sg[0] = 0
memset(vis, 0, sizeof vis);
for(j = 0; j <= 9 && i >= op[j]; j++) {
vis[sg[i - op[j]]] = 1; //将点i的后继点的sg值加入集合
}
for(j = 0; ; j++) {
if(vis[j] == 0) { //找最小的不在该集合中的数,更新
sg[i] = j;
break;
}
}
}
}
int main() {
int n;
getsg();
while(~scanf("%d", &n)) {
if(sg[n]) printf("Kiki\n");
else printf("Cici\n");
}
return 0;
}

本文解析了一道巴什博弈的变形题,通过分析得出先手必胜的条件,并提供了两种实现方法:直接判断和使用SG函数。对于初始牌堆数量不是3或3的倍数的情况,先手玩家总是能赢得比赛。
7915

被折叠的 条评论
为什么被折叠?



