2014携程第二场1004 夺旗 Nim变形

题目链接:夺旗

Problem Description

小时候玩过一种小游戏,夺旗。游戏规则:共有N组旗子,每组旗子数量已知,两个玩家轮流拔旗,每次只能选
一组,拔掉一定数量的旗子,至少需要拔一个,拔掉旗子之后,还可以将该组旗子中余下的任意多个旗子中
任选几个放到其它的任意一组或几组里。一堆旗子被拔空后就不能再往此处插旗了。先无法拔旗的人为输者。


假设每次都是你先拔旗子,且每个player都足够聪明,现在给你旗子的组数、每组旗子的数量,请判断出你能
否获胜。


例如:如果最开始有4组旗子,旗子个数分别为3 1 4 2,而你想决定要先拿走第三组旗子中的两个旗子,旗子
个数变为3 1 2 2,然后他可以使旗子组达到的状态有以下几种:

3 1 2 2(不移动)

4 1 1 2(移动到第一组一个)

3 2 1 2(移动到第二组一个)

3 1 1 3(移动到第四组一个)

4 2 0 2(移动到第一组一个,第二组一个)

4 1 0 3(移动到第一组一个,第四组一个)

3 2 0 3(移动到第二组一个,第四组一个)

5 1 0 2(全部移动到第一组)

3 3 0 2(全部移动到第二组)

3 1 0 4(全部移动到最后)

Input

可能有多组测试数据(测试数据组数不超过1000)
每组测试数据的第一行是一个整数,表示N(1<=N<=10)
第二行是N个整数分别表示该组旗子中旗子的数量。(每组旗子数目不超过100)

当输入的N为0时,表示输入结束输出对于每组测试数据。

Output

Win表示你可以获胜,输出Lose表示你必然会败。

Sample Input

3
2 1 3
2
1 1
0

Sample Output

Win
Lose

Source

CodingTrip - 携程编程大赛 (预赛第二场)


本质:

Nim游戏变形


思路:

n=1的情况不用考虑,考虑n=2的情况,注意到当两堆石子的数量一样的时候,无论先手做何操作,只要后手模仿先手的操作即可回到两堆石子数量一样的状态,类比n=2的情况,在n=4的时候只要有两对石子的个数是一样的也必败,后手同样只要模仿先手的操作即可,以此类推。

那么当石子数不是两两配对的时候呢?那么只要将石子个数排序,然后把最多的一堆石子变成和最少的一堆石子一样多,再将多余出来的石子分配给中间的堆,使其两两配对即可,至于为什么一定可以将其两两配对,只要将中间石子两两的差投影到y轴即可证明。

那么n为偶数的情况就解决了,至于n为奇数的情况,只要将最多的那堆取完,再把多余的石子分配给剩下的使其两两配对即可,证明同上。


#include<stdio.h>
#include<stdlib.h>
int cmp(const void *a,const void *b)
{
    return *(int *)a>*(int *)b?1:-1;
}
int k[15];
int main()
{
    int i,n;
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0)
            break;
        for(i=0;i<n;i++)
            scanf("%d",&k[i]);
        if(n&1)
        {
            printf("Win\n");
            continue;
        }
        qsort(k,n,sizeof(k[0]),cmp);
        for(i=0;i<n;i++)
            if((i&1)&&k[i]!=k[i-1])
                break;
        if(i>=n)
            printf("Lose\n");
        else
            printf("Win\n");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值