poj 1704 #博弈 转化为取石子

来源:互联网 发布:seo文章内链 编辑:程序博客网 时间:2024/06/05 17:46

先是正文,后是转载。因为看了这文章才找的这道题,尽管两者并不完全是一回事。


poj

1704

问题描述:GeorigiaBob玩棋子的游戏,棋子是排在同一行的,每人每次可以移动一个棋子,移动的格数不限,但移动只能向左,且不能超过左边的棋子。当谁没有棋子可移时,谁就输了。女士优先原则,Georgia总是优先。

解题思路:

我们把棋子按位置升序排列后,从后往前把他们两两绑定成一对。如果总个数是奇数,就把最前面一个和边界(位置为0)绑定。

在同一对棋子中,如果对手移动前一个,你总能对后一个移动相同的步数,所以一对棋子的前一个和前一对棋子的后一个之间有多少个空位置对最终的结果是没有影响的。

如果对手移动后一个,就相当于取走石子

于是我们只需要考虑同一对的两个棋子之间有多少空位。

这样一来,题目就转换成了就成了POJ 1067 取石子问题,直接对每一段空位置的长度求异或就可以了。

#include <stdio.h>#include <algorithm>#define N 1001int main(){    int n,a[N],d[N],i,j,t;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        for(i = 1; i <= n; ++i)            scanf("%d",a + i);        std::sort(a+1,a + 1 + n);        for(i = n,j = 0;i > 1;++j, i -= 2)            d[j] = a[i] - a[i-1] - 1;        if(i)            d[j++] = a[i] - 1;        for(i = 1; i < j; ++i)            d[0]^= d[i];        printf(d[0] ? "Georgia will win\n":"Bob will win\n");    }    return 0;}




(转)

我谈阶梯博弈( Staircase Nim )

分类: 博弈 493人阅读 评论(4)收藏举报
今天在POJ做了一道博弈题..进而了解到了阶梯博弈...下面阐述一下我对于阶梯博弈的理解..
首先是对阶梯博弈的阐述...博弈在一列阶梯上进行...每个阶梯上放着自然数个点..两个人进行阶梯博弈...每一步则是将一个集体上的若干个点( >=1 )移到前面去..最后没有点可以移动的人输..


如这就是一个阶梯博弈的初始状态 2 1 3 2 4 ... 只能把后面的点往前面放...如何来分析这个问题呢...其实阶梯博弈经过转换可以变为Nim..把所有奇数阶梯看成N堆石子..做nim..把石子从奇数堆移动到偶数堆可以理解为拿走石子..就相当于几个奇数堆的石子在做Nim..( 如所给样例..2^3^4=5 不为零所以先手必败)为什么可以这样来转化?
假设我们是先手...所给的阶梯石子状态的奇数堆做Nim先手能必胜...我就按照能赢的步骤将奇数堆的石子移动到偶数堆...如果对手也是移动奇数堆..我们继续移动奇数堆..如果对手将偶数堆的石子移动到了奇数堆..那么我们紧接着将对手所移动的这么多石子从那个奇数堆移动到下面的偶数堆...两次操作后...相当于偶数堆的石子向下移动了几个..而奇数堆依然是原来的样子...即为必胜的状态...就算后手一直在移动偶数堆的石子到奇数堆..我们就一直跟着他将石子继续往下移..保持奇数堆不变...如此做下去..我可以跟着后手把偶数堆的石子移动到0..然后你就不能移动这些石子了...所以整个过程..将偶数堆移动到奇数堆不会影响奇数堆做Nim博弈的过程..整个过程可以抽象为奇数堆的Nim博弈...
其他的情况...先手必输的...类似推理...只要判断奇数堆做Nim博弈的情况即可...
为什么是只对奇数堆做Nim就可以...而不是偶数堆呢?...因为如果是对偶数堆做Nim...对手移动奇数堆的石子到偶数堆..我们跟着移动这些石子到下一个奇数堆...那么最后是对手把这些石子移动到了0..我们不能继续跟着移动...就只能去破坏原有的Nim而导致胜负关系的不确定...所以只要对奇数堆做Nim判断即可知道胜负情况...