首页 > 代码库 > hdu 4111 Alice and Bob(博弈)
hdu 4111 Alice and Bob(博弈)
题目链接: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;
}
hdu 4111 Alice and Bob(博弈)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。