hdu 4315 Climbing the Hill 博弈问题,可转化为nim游戏问题,多校联合赛(二)第六题
博弈问题,先考虑如果总数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)运算。
为什么可以a1^a2^...^an=0 就判断先取的一定赢呢,首先是如果堆内的石子数量成对相等,这个应该都明白,就是2,2的情况或者4,4,9,9,这样,谁先取谁输,但如果是三组的呢,怎么办,用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了这不就是成对了么,就业是为什么a1^a2^...^an=0就可一判断谁先走谁输了
以上都是自己的一些理解,如有错误请指正哈!!!!(*^__^*) 嘻嘻……
代码如下
#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"); }}