hdu3389
2015-08-31 21:26
134 查看
HDU 3389 (Nim博弈变形) Game
参考了众巨巨的博客,现在重新整理一下自己的思路。首先在纸上画了一下转移图:
![](http://images.cnitblog.com/blog2015/640481/201504/251416559062797.png)
1 3 4号盒子是不能够再转移卡片到其他盒子中去了的,其他盒子中的卡片经过若干步的转移最终也一定会转移到1 3 4号盒子中去。
具体来说,n % 6 == 0 或 2 或 5的盒子,经过奇数步转移到1 3 4中去,其他的则须经过偶数步才能转移过去。
下面来证明,所有卡片都在偶数步盒子中是必败状态。
因为不论先手将偶数步的盒子中卡片移走了多少,后手一定可以把这些卡片再往前移动一个盒子,直到移到1 3 4中去为止。
对于只有一个盒子有卡片,而且这个盒子是奇数步盒子来说,先手必胜。
很简单,根据上面的结论,只要先手把这个奇数步盒子中所有卡片全部往下移一个盒子就好了。这样就转移到了先手必败状态。
整个游戏可以看做若干个子游戏的和游戏,偶数步盒子不予考虑,只考虑奇数步盒子中的卡片,这就相当于一个n堆石子的Nim游戏。
在一个奇数步盒子中移走k张卡片,相当于在某一堆石子中取走k个石子。把所有石子取完相当于,所有的卡片都在偶数步的盒子里面,而我们已经证明完这种状态是必败状态了。
所以在代码中就只需要将奇数步盒子中的卡片数异或一下求个Nim和,就能判断胜负了。
![](http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
![](http://common.cnblogs.com/images/copycode.gif)
1 #include <cstdio> 2 3 int main() 4 { 5 //freopen("in.txt", "r", stdin); 6 7 int T; scanf("%d", &T); 8 for(int kase = 1; kase <= T; kase++) 9 { 10 int n; scanf("%d", &n); 11 int a, sum = 0; 12 for(int i = 1; i <= n; i++) 13 { 14 scanf("%d", &a); 15 if(i%6==0 || i%6==2 || i%6==5) sum ^= a; 16 } 17 printf("Case %d: %s\n", kase, sum ? "Alice" : "Bob"); 18 } 19 20 return 0; 21 }
![](http://common.cnblogs.com/images/copycode.gif)
【推荐原因】:这篇博文讲的比较直白方便理解,其实这道题不难,不要理解错了就行,就像我一开是把题目中的A,B理解成盒子中卡片的数量了,就直接做不出来了,卡了几个小时!所以由此可见,认真读题是多么的重要!!!
【原文链接】:http://www.cnblogs.com/AOQNRMGYXLMV/p/4455908.html
相关文章推荐
- Linux学习四:UDP编程(上)
- Linux学习三:Ubuntu下使用minicom和开发板通信
- php正则表达式获取表格内容
- HDU 5154 Harry and Magical Computer(找环)
- CentOS下安装软件的方法
- Jsp分页实例---真分页
- Linux学习二:Makefile基础
- TopCoder SRM 666 Div2 Problem 999 - WalkOverATreeDiv2 (树形DP)
- OSI七层模型
- 数据库设计(2)生命周期
- linux select 模型详解
- scala 学习笔记(07) 一等公民的函数
- php大力力 [040节] 买了一天域名,整了一天后台,新网后台不懂啊
- 初进hp感想和目标
- HDU DFS
- 枚举类型的使用
- where、having、group by、order by的顺序
- Hibernate自学详细笔记
- 百度面试题 最长公共子串-动态规划法
- Linux学习一:安装/配置vi,熟悉gcc/vi