[BZOJ1115][POI2009]石子游戏Kam解题报告|阶梯博弈

有N堆石子,除了第一堆外,每堆石子个数都不少于前一堆的石子个数。两人轮流操作每次操作可以从一堆石子中移走任意多石子,但是要保证操作后仍然满足初始时的条件谁没有石子可移时输掉游戏。问先手是否必胜。

 

  首先直接考虑题中的条件并没有办法入手

  每堆石子的个数不少于前一堆石子的个数可以看成是相邻两堆石子时间的个数差保持>=0

  于是可以把这些石子差看做石子

  每次操作会将其中一堆石子减去一个值,又会将它后面的一堆加上相等的值

  就可以看做是把这一堆推到它后面的一堆

  于是转化成了阶梯博弈

 

 


 

 

  阶梯博弈

  描述大概就是:

  两个人在阶梯上玩推石子游戏,每人操作可以将某堆的任意多石子向左推一阶

  所有的石子都推到阶梯下了即算成功

 

  我们可以只考虑在奇数堆上的操作,这样整个游戏就可以转化成NIM的模型

  玩家将奇数堆中的石子推到偶数堆,可以看做是从奇数堆中取走了若干石子

  两人一直把奇数堆的石子推向偶数堆,就可以用SG函数来判断胜负

  然而如何考虑偶数堆呢?如果对方将偶数堆的石子推向了奇数堆

  那么我们就可以把这些石子再往左推推向更左边的偶数堆

  这样一个回合,奇数堆中的状态并没有改变,玩家的顺序也并没有改变

  但是偶数堆却慢慢地向阶梯下移

  也就是说偶数堆的情况我们完全不用去考虑

 

 


 

 

  然而这道题是反过来的阶梯博弈,即将石子向后推

  注意是从n开始判断的奇偶

 

 

program xjt5;
var test,tt,i,n,ans:longint;
    a:array[-1..1010]of longint;

begin
    readln(test);
    for tt:=1 to test do
    begin
        readln(n);a[0]:=0;
        for i:=1 to n do read(a[i]);readln;
        i:=n;ans:=0;
        while i>0 do
        begin
            ans:=ans xor (a[i]-a[i-1]);
            dec(i,2);
        end;
        if ans>0 then writeln('TAK') else writeln('NIE');
    end;
end.

 

 

 

  

  

posted @ 2015-04-29 10:59  mjy0724  阅读(863)  评论(0编辑  收藏  举报