HDU 4315 Climbing the Hill Staircase Nim变种

来源:互联网 发布:nginx源码剖析 pdf 编辑:程序博客网 时间:2024/04/29 06:17

题意:在山上有n个人,每个人编号是1~n,这些位置只能同时被一个人占据,但是山顶可以同时被多个人占据,距离山顶第k近的是King,现在Alice和Bob开始向上
          送人,条件是不能跨越前面最近的人,问在Alice先手,双方最优的条件下谁能把King送到山顶。

题解:这个题是2012多校第二场的题目,也是2011年大连站regional热身赛的题目。

          Staircase Nim的变种,Staircase Nim就是将所有奇数位置的可行方法数异或起来。

          对于这个题目:当k=1时,Alice必胜;

                               当k!=1时,两两分组,当k在组内后面时候,是朴素的Staircase Nim;当k在组内前面时候,依旧是朴素的Staircase Nim,只不过前面组最
                               后一个球最后不是移动到0,而是1; 不过此时,如果前面只有一个球时,Alice和Bob都不愿移动前面的球到0,所以此时前面球有hill[1]-1种
                               选择,所以hill[1]--;之后按照Staircase Nim继续做下去。


       说说Staircase Nim:即有n堆石子放在阶梯上,两个人轮流进行,每一步则是将一个阶梯上的若干个石子( >=1 )移到前面阶梯上,直到0阶梯为止,最后没有石子可以移动的人输。将奇数阶梯上的石子数异或起来,答案不为0那么先手胜。解释:首先后手一定能保证奇数阶梯上的平衡态不变,即如果先手将偶数阶梯石子x个移动到奇数阶梯,那么后手把这x个石子继续移动到下一个偶数阶梯,这样保证奇数阶梯上的平衡态不变;如果先手将奇数阶梯棋子x个移动到偶数阶梯,那么后手一定可以通过移动其他奇数阶梯保证奇数阶梯上的平衡态不变(如5 2 1 0 4,先手把5移动到0号阶梯,后手可以把4中3个石子移动到4号阶梯,这个可以看成异或的性质)。这样需要看开始的奇数阶梯上的状态是否平衡即可,如果不为零先手可以移动相应石子使其平衡,从而必胜。因为最终在0号阶梯上的石子不能继续移动,所以需要得到的是奇数阶梯上的平衡态而不是偶数阶梯(因为最后一定是奇数到偶数即1->0)。
     
       对于这个题目,从后向前两两划分成一组,组内相当于奇数阶梯上的石子,组间相当于偶数阶梯上的石子,移动组内的前面石子一定能够通过移动当前组的后面石子相同步数达到平衡态,移动组内后面的石子一定能够通过移动其他组后面石子达到平衡态,具体因为King的原因需要处理细节,上面已经说清楚了,不再赘述。


Sure原创,转载请注明出处。

#include <iostream>#include <cstdio>#include <algorithm>using namespace std;const int maxn = 1002;int hill[maxn];int n,k;void solve(){    hill[0] = 0;    for(int i=1;i<=n;i++)    {        scanf("%d",&hill[i]);    }    if(k == 1)    {        puts("Alice");        return;    }    sort(hill+1,hill+n+1);    int ans = 0;    if(k == 2 && n & 1)   //如果前面只有一个人并且King是第二个人时    {        hill[1]--;  //前面人可行的方法数--;    }    for(int i=n;i>=1;i-=2)   //Staircase Nim模型    {        ans ^= (hill[i] - hill[i-1] - 1);    }    if(n & 1) ans ^= hill[1];    puts(ans ? "Alice" : "Bob");    return;}int main(){    while(~scanf("%d %d",&n,&k))    {        solve();    }    return 0;}


原创粉丝点击