ZOJ 3964 Yet Another Game of Stones (博弈)

1 篇文章 0 订阅

Alice and Bob are playing yet another game of stones. The rules of this game are as follow:

  • The game starts with n piles of stones indexed from 1 to n. The i-th pile contains ai stones and a special constraint indicated as bi.

  • The players make their moves alternatively. The allowable moves for the two players are different.

  • An allowable move of Bob is considered as removal of some positive number of stones from a pile.

  • An allowable move of Alice is also considered as removal of some positive number of stones from a pile, but is limited by the constraint bi of that pile.

    • If bi = 0, there are no constraints.
    • If bi = 1, Alice can only remove some odd number of stones from that pile.
    • If bi = 2, Alice can only remove some even number of stones from that pile.

    Please note that there are no constraints on Bob.

  • The player who is unable to make an allowable move loses.

Alice is always the first to make a move. Do you know who will win the game if they both play optimally?

解题思路

此题的题意比较容易理解,可以简单的看着 Nim 博弈的变种。但问题在于 Alice 对第 i 堆石子的取法必须根据 bi 确定。所以如果这个问题能够归结到正常的 Nim 博弈(取石子问题),则很容易解决。

考虑特判存在 bi=1  bi=2 的情况:

  • 如果存在第 i 堆石子,其 ai 为奇数且 bi=2 ,则 Bob 必胜(Alice 在最优策略下无法取完该堆,但 Bob 可以)。
  • 如果存在 2 个及以上 bi=2 bi=1  ai>1 的情况,则 Bob 必胜。
  • 如果只有一个 bi=2 (其余都为 bx=0 ) 的情况,则 Alice 为了胜利,必须先将该堆石子取完(否则 Bob 只需取掉该堆 1 个石子, Bob 必胜)。此时问题等同于 n-1 堆石子,Bob 先手的 Nim 博弈。
  • 如果只有一个 bi=1  ai>1 (其余都为 bx=0 )的情况,Alice 同样需先将该堆石子取完(或只剩一个)。此时问题等同于 n-1(n) 堆石子,Bob 先手的 Nim 博弈。

对于只有 bi=0 的情况,Nim 博弈全部 ai 异或即可。

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[N], b[N], n;
bool jug()
{
    int cnt[3] = {0, 0, 0}, tot = 0;
    for(int i=1;i<=n;i++)
    {
        if(a[i]%2 && b[i] == 2) return false;
        if(b[i] == 2)   cnt[2]++,   cnt[0]++;
        if(a[i] > 1 && b[i] == 1)   cnt[1]++,   cnt[0]++;
    }
    if(cnt[0]>1)    return false;
    if(cnt[1] == 1) {
        for(int i=1;i<=n;i++)
            if(b[i] == 1 && a[i] > 1)   tot ^= (a[i]%2?0:1);
            else    tot ^= a[i];
        return !(tot?1:0);
    }
    else if(cnt[2] == 1) {
        for(int i=1;i<=n;i++)
            if(b[i] != 2)
                tot ^= a[i];
        return !(tot?1:0);
    }
    else {
        for(int i=1;i<=n;i++)
            tot ^= a[i];
        return tot;
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)
            scanf("%d",&b[i]);
        printf("%s\n", jug() ? "Alice" : "Bob");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值