您的位置:首页 > 其它

hdu 4111 Alice and Bob(博弈)

2014-11-09 19:45 555 查看
题目链接:hdu 4111 Alice and Bob

题目大意;Alice和Bob两个玩游戏,有N堆石子,每次可以从一堆中取走一个石子,或者是合并两堆石子,Alice先,问

说最后谁赢。

解题思路:NP定理,写出一些NP定理找到规律,再用归纳的方法证明。

统计1的个数c,以及非1情况下的步数s,包括合并。
c为奇数,s不等于2:那么先手必胜。
s为2或者为0:c为3的倍数是先手必败。
否则的话,s为奇数时先手必胜。

首先没有1的情况下很好证明,就是总的步数和为奇数时为先手必胜态,N点。相反,如果为偶数就是P点。(这种情况

下必胜的人只要保证任意一堆石子的个数不会小于2即可,直到最后只剩下一堆,因为1是一个比较特殊的存在)

再者证明奇数个1且s不为2的时候为必胜态,从一个1的开始,假设现在有一个1和s,如果s为奇数,那么先手可以合并

两堆石子;如果s是偶数,先手可以拿走1;所以这种情况下一定是先手必胜,因为移动1可以选择少掉一步或者两步。

那么现在就是两个1和s的情况,如果其中一个人先消耗掉一个1,和s合并,那么剩下的状态是(1,s+1)的N点;取走1,

剩下(1,s)同样是N点;合并两个1,(2,s)==>(s+3)的状态,如果s为奇数,那么即为P态,对应的刚才先手就是必胜,反之

则是必败,这种情况归纳到结论中的第三条。那么三个1的情况下就可以消耗一个1更变s的奇偶性。

不过在s=2或者s=0的时候属于特殊情况,因为2去掉一个之后就变成了1,s为0时为全1,通过上面的规律,我们已经知

道了1是比较特殊的。那么现在有NP图



不难发现,这是c如果是3的倍数,那么一定是先手必败态。
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

bool judge (int c, int s) {
if (c&1 && s > 2)
return true;

if (s == 0 || s == 2)
return c % 3;
return s&1;
}

int main () {
int cas;
scanf("%d", &cas);
for (int kcas = 1; kcas <= cas; kcas++) {
int n, s = 0, c = 0, x;

scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &x);
if (x == 1)
c++;
else {
if (s == 0)
s = x;
else
s += x + 1;
}
}
printf("Case #%d: %s\n", kcas, judge(c, s) ? "Alice" : "Bob");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: