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

来源:互联网 发布:java中的23种设计模式 编辑:程序博客网 时间:2024/06/03 01:56

题目链接:夺旗

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

32 1 321 10

Sample Output

WinLose

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;}

0 0
原创粉丝点击