ZCMU—1207

1207: 取宝石

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 39   Solved: 9
[ Submit][ Status][ Web Board]

Description

Tom和Jerry在玩一个取宝石的游戏,游戏开始前,他们将n(1<=n<=1000)个盘子摆在一条线上,每个盘子里均放有一定数量的宝石,之后
Tom和Jerry轮流取宝石,取宝石的规则如下:每次取宝石者必须选中一个盘子,然后从盘中取走至少1颗宝石,之后将该盘子中剩下的宝
石以任意分配方式分配到其他的盘子中,也可以不向外分配。如此轮流进行下去,直到某一方再也不能取宝石时,对方获胜。现在Jerry
率先取宝石。假设Tom和Jerry同样聪明,在给定盘子中宝石数量序列的情况下,Jerry能否获胜呢?

Input

输入包括多组测试数据,每组测试数据的第一行为一个正整数n,第二行包括n个整数,第i个整数表示第i个盘子中宝石的数量,每个盘子
中宝石的数量不超过500。当n=0时输入结束。

Output

对于每组测试数据,输出1行,若Jerry能获胜,输出“Yes”,否则输出“No”。

Sample Input

3
2 1 3
2
1 1
0

Sample Output

Yes
No

【分析】

讲真这种博弈我就只会找规律.....

从最小的开始考虑,如果每个盘子上的宝石都是1,那么总数为奇数的时候Jerry一定获胜

如果两个人每次都只把一个盘子上的宝石取完,那么总数为奇数的时候Jerry一定获胜

在这两个最简单的情况下,猜测盘子是奇数是Jerry会获胜....

那么模拟正常情况,如果不是全1,那么显然不管你怎么拿,Jerry保证每次拿完宝石后将场上有宝石的盘数补全成奇数个就可以了。

那么这种情况下的最基础的情况就是盘中的宝石数量只有1和2,因为1拿完就没有了,2只能留下自己或者拿完,宝石数如果大于2就可以往外补全。

那么如果不是全1,考虑1 1 1 1 2这个情况,那么显然Jerry拿光2就可以获胜,

那么再考虑1 1 1 2 2 这个情况,那么显然Jerry拿1,然后模仿Tom拿就可以了

所以1 1 2 2 2情况类似第一种,Jerry拿掉一组2 然后跟着Tom就可以了。

之后的情况都类似上面的情况。

所以可以发现,当盘子总数为奇数的时候,Jerry一定获胜。

那么当盘子总数为偶数时,

考虑最简单的一种情况就是2 2,发现这个情况下Jerry是会输的,然后继续考虑2 3,发现Jerry可以获胜,因为2 2的情况后手获胜,所以在2 X的情况Jerry只要拿成2 2就可以获胜。

3 3也一样,所以在只有两个盘子的情况下,如果两个盘上的宝石数量一样,那么Jerry就会失败,其他情况都可以获胜。

那么再做一次猜测,盘子数量是偶数时,只有盘中宝石数全部一样,Jerry才会失败。

那么考虑2 2 2 2这种情况,这种情况下Jerry是必败的,因为不管Jerry怎么拿,Tom只要模仿就可以了。

(但是事实证明提交之后是WA的....所以也就是考虑的情况有问题....)

再考虑2 2 2 3这种情况,可以发现,2 2 2 2是先手失败,那么2 2 2 3,Jerry只要拿走3中的一个1,变成2 2 2 2,Jerry就能获胜

所以再考虑2 2 3 3这种情况,这种情况下,Tom只要模仿Jerry就可以获胜。

所以发现了之前的问题,也就是说并不是全部宝石数一样的时候会失败,而是每种宝石数成对出现的时候会失败,也就是每种宝石出现次数为偶数的时候,所以也可以回过头去证明当盘子总数是奇数的时候Jerry会获胜...

所以代码很简单....

如果盘数n是奇数,那么Jerry获胜

如果盘数n是偶数,那么排序之后判断一下每个i和i+1是否一样就可以(i为从0开始的偶数),如果出现不一样的情况就Jerry就可以获胜。否则Tom获胜

以上是一只菜鸡做这题的心路历程.......感觉自己真的菜.......继续学习...希望以后能写出比较有水准的题解...

【代码】

#include <stdio.h>
#include <algorithm>
using namespace std;
int a[10000];
int main()
{
    int n;
    while (~scanf("%d",&n)&&n)
    {
        for (int i=0;i<n;i++) scanf("%d",&a[i]);
        if (n%2)
            printf("Yes\n");
        else
        {
            sort(a,a+n);
            for (int i=1;i<n;i+=2)
                if (a[i]!=a[i-1])
                {
                    printf("Yes\n");
                    goto out;
                }
            printf("No\n");
            out:;
        }
    }
    return 0;   
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值