nyoj-137 取石子(三) (博弈,楼教主真男人八题)

取石子(三) 时间限制: 1000 ms|内存限制: 1000 KB 难度: 6

描述
小王喜欢与同事玩一些小游戏,今天他们选择了玩取石子。
游戏规则如下:共有N堆石子,已知每堆中石子的数量,两个人轮流取子,每次只能选择N堆石子中的一堆,取一定数量的石子(最少取一个),取过子之后,还可以将该堆石子中剩下的任意多个石子中随意选取几个放到其它的任意一堆或几堆上。等哪个人无法取子时就表示此人输掉了游戏。注意,一堆石子没有子之后,就不能再往此处放石子了。
假设每次都是小王先取石子,并且游戏双方都绝对聪明,现在给你石子的堆数、每堆石子的数量,请判断出小王能否获胜。
例如:如果最开始有4堆石子,石子个数分别为3 1 4 2,而小王想决定要先拿走第三堆石子中的两个石子(石子堆状态变为3 1 2 2),然后他可以使石子堆达到的状态有以下几种:
3 1 2 2(不再移动石子)
4 1 1 2(移动到第一堆一个)
【nyoj-137 取石子(三) (博弈,楼教主真男人八题)】 3 2 1 2(移动到第二堆一个)
3 1 1 3(移动到第四堆一个)
5 1 0 2(全部移动到第一堆)
3 3 0 2(全部移动到第二堆)
3 1 0 4(全部移动到最后)
输入
可能有多组测试数据(测试数据组数不超过1000)
每组测试数据的第一行是一个整数,表示N(1<=N<=10)
第二行是N个整数分别表示该堆石子中石子的数量。(每堆石子数目不超过100)
当输入的N为0时,表示输入结束
输出
对于每组测试数据,输出Win表示小王可以获胜,输出Lose表示小王必然会败。
样例输入
3 2 1 3 2 1 1 0

样例输出
Win Lose



思路:
楼教主真男人八题之一,感觉确实不好想,以下为本题分析:
1、n = 1(n表示石子堆数)时,那么先手必胜;
2、n = 2 时,若两堆石子数相等,那么先手必败,否则,先手必胜!
比如,先说必败态,两堆石子数相等:
若两堆石子数为[1,1],显然先手必败;
若石子数为[m,m](m >= 2) ,那么无论先手怎么取,后手都能再将两堆石子数置为相等,最终置成[1,1]的必败状态,所以此时为必败态!
而两堆石子不相等时,先后可以将两堆取相等,那么后手将要面对的就是上述必败态了!
3、n = 3 时,先手可以先取石子数最多的一堆,同时将另两堆配平,此时后手必败!
4、n = 4 时,若出现[x,x,y,y]或[x,x,x,x]状态,先手必败,因为无论先手怎么取,后手都能给先手置出两堆石子数相等的情况(即留给先手必败态);后则,先手即可给后手制造必败态!
。。。。
总结:
n 为奇数: 必胜
n 为偶数:若相同石子数量的次数的堆数偶是有偶数个,则后者胜,只要有一个不是偶数那么先者胜

代码:

#include #include int ct[103]; // 记录某个石子数出现的次数(有ct[k]堆有k个石子)int main() { int n, i; while(scanf("%d", &n), n){ int cur; memset(ct, 0, sizeof(ct)); for(i = 0; i < n; i ++){ scanf("%d", &cur); ct[cur] ++; }if(n % 2 != 0){// 有奇数堆石子,先手必胜 printf("Win\n"); continue; } int bz = 0; for(i = 0; i <= 100; i ++){ if(ct[i] % 2 != 0){// 再有偶数堆石子,且有偶数堆石子数=ct[i],则必胜 bz = 1; break; } } if(bz) printf("Win\n"); else printf("Lose\n"); }return 0; }




    推荐阅读