阶梯博弈(bzoj1115,nefu 1783)石子游戏Kam

本文介绍了一种名为阶梯博弈的游戏策略,通过分析石子分布和差值变化,将其转化为尼姆博弈问题。阐述了如何利用奇偶阶梯上的石子数量及其异或性质来确定先手是否有必胜策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description
有N堆石子,除了第一堆外,每堆石子个数都不少于前一堆的石子个数。两人轮流操作每次操作可以从一堆石子中移走任意多石子,但是要保证操作后仍然满足初始时的条件谁没有石子可移时输掉游戏。问先手是否必胜。
Input
第一行u表示数据组数。对于每组数据,第一行N表示石子堆数,第二行N个数ai表示第i堆石子的个数(a1<=a2<=……<=an)。 1<=u<=10 1<=n<=1000 0<=ai<=10000
Output
u行,若先手必胜输出TAK,否则输出NIE。
Sample Input
2
2
2 2
3
1 2 4
Sample Output
NIE
TAK
**

阶梯博弈

**
阶梯博弈的模型如下
给出N个台阶,每个台阶上有ai个石子,把地面当做台阶0,双方轮流操作,每次将一个台阶上,至少选1个,最多全取,的石子取出,并放在左边一个台阶上,没有操作策略的人输(此时所有石子都在地面上),问先手是否有必胜策略。
在这里插入图片描述
可以把阶梯博弈看作在奇数号阶梯上取石子的尼姆博弈。
当每个奇数阶梯上的石子数异或为0(这里与数的二进制分解有关,感觉应该是尼姆博弈中最重要的部分了),可以通过把一部分石子推到前一阶梯来把异或和变成0——这意味着对于每一个奇数阶梯上的石子,它的子堆都在另外一堆中有所对应,也就是说(在把异或和变为0之后)先手可以通过模仿后手的操作,使得先手能取完奇数阶的最后一个石子。
那么来讨论偶数阶,现在到了后手取石子。后手把偶数阶的石子推到它的前一阶梯(偶数前一阶肯定是一个奇数阶),先手就在把这些石子往前推一阶,也就是那部分又到了偶数阶上。因为0是偶数,这样进行下去,肯定是先手把最后一枚石子推到0上。此时不可操作,后手败。
**

本题

**
虽然很难看出来。。。
注意两堆石子之间的差值,来看i-1,i,i+1三堆,当从i堆拿走x个石子,那么i-1与i的石子数相差值减x,而i与i+1的石子数相差值加x。因为保证所给石子数递增,也就保证了差值>=0。这差值就相当于阶梯博弈中阶梯上的石子数,i与i+1差值在较高的阶梯,i-1与i差值在较低阶梯上。
那么这就是一个阶梯博弈了。当每个差值都变为0(这里尤其注意题目所给出的第一堆石子与0的差值,其实对应阶梯博弈最高一级阶梯),就相当于把所有石子都移动到地面上了。
这个题就解决了!

**

代码

**

#include <iostream>
#include <cstdio>
using namespace std;
int a[1005];
int main()
{
    int u,n,x,ans,cnt;
    scanf("%d",&u);
    while(u--)
    {
        ans=0;
        cnt=1;
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
         scanf("%d",&a[i]);
        for(int i=n;i>=1;i--)
        {
         if(cnt%2) ans^=a[i]-a[i-1];
         cnt++;
        }
        if(ans)
            printf("TAK\n");
        else
            printf("NIE\n");
    }
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值