您的位置:首页 > 其它

hdu 4315 Climbing the Hill 博弈问题,可转化为nim游戏问题,多校联合赛(二)第六题

2012-07-29 08:30 471 查看
博弈问题,先考虑如果总数n为偶数(k!=1),当n个点全两两挨在一起时,谁先走谁输(自己模拟吧)

当总数n为奇数时(k!=1),先吧第一个点走道终点,然后就是偶数的情况了,然后考虑怎么将他们两两挨在一起(注意不用所有点都挨在一起)

这是就是当n为偶(k!=1)计算a[i+1]与a[i]的距离,for(i+=2),这样我们就将它化成几点nim游戏问题,将a[i+1]与a[i]的距离左为每堆石子的个数

当n为奇数,就是a【1】自己当作一个堆,然后还是将a[i+1]与a[i]的距离左为每堆石子的个数,轮到谁没有石子取了,谁就输啦!当然注意特殊情况就是当n为奇数的时候,k如果为2,前面我们说当n为奇数是直接将第一个直接走到终点,但因为第二哥是k了,所以第一个a[i]不能走道终点,只能走道里终点最近的位置也就是只能走a[i]-1步,所以就是将a[i]-1当作一个堆

再说一下什么是nim游戏

通常的Nim游戏的定义是这样的:有若干堆石子,每堆石子的数量都是有限的,合法的移动是“选择一堆石子并拿走若干颗(不能不拿)”,如果轮到某个人时所有的石子堆都已经被拿空了,则判负(因为他此刻没有任何合法的移动)。



对于一个Nim游戏的局面(a1,a2,...,an),它是P-position当且仅当a1^a2^...^an=0,其中^表示异或(xor)运算。

为什么可以[u]a1^a2^...^an=0 就判断先取的一定赢呢,首先是如果堆内的石子数量成对相等,这个应该都明白,就是2,2的情况或者4,4,9,9,这样,谁先取谁输,但如果是三组的呢,怎么办,用[u]a1^a2^...^an=0,啊!!简洁的说就是将所有堆数全都分解成二进制堆,譬如9,5,12,谁先取谁输,为什么,就是9的二进制1001分成8和1,5的二进制0101分成4和1,12的二进制1100分成8和4,然后9,5,12就变成1,1,4,4,8,8了这不就是成对了么,就业是为什么[u]a1^a2^...^an=0就可一判断谁先走谁输了[/u][/u][/u]

以上都是自己的一些理解,如有错误请指正哈!!!!(*^__^*) 嘻嘻……

代码如下

#include<iostream>
#include<cstdio>
using namespace std;
int a[1005],ans;
int n,k;
void move(){
int i;
if(n%2==0){
for(i=1;i<=n;i+=2){
ans^=(a[i+1]-a[i]-1);
}
}
else{
ans^=a[1];
for(i=2;i<=n;i+=2){
ans^=(a[i+1]-a[i]-1);
}
}

}
int main(){

while(~scanf("%d%d",&n,&k)){
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
ans=0;
if(k==1) {
printf("Alice\n");
continue;
}
if(k==2 && n%2==1){
a[1]--;
move();
}
else move();
//        cout<<ans<<endl;
if(ans==0) printf("Bob\n");
else printf("Alice\n");
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: