leetcode 每日一题 Nim Game
2016-02-29 15:17
197 查看
题目意思比较简单,就是你和朋友拿桌上的一堆石子,每次可以选择拿1-3颗,拿走最后一颗石子的人将胜利,如你先拿,怎样判断你是否能赢?
题目是最简单的博弈论问题,解决方法是如果桌上石子能被4整除,则必输。如果桌上石子不能被4整除,则有必赢的策略。
如果可以取得的最大数为m,则n%(m+1)为判断是否能赢的条件。
大牛写法为:
之前的nim游戏是没有规定必须取多少个“石子”的,玩法是,放置3,4,5三列硬币,可以从某一列硬币中取走1~全部,最后拿走的人获胜。
关于这个的策略,人们发现从第一列3个硬币里取走2个,之后可以必胜。
取胜方法可以使用二进制来表示,并做nim加法,引用果壳的文章如下:
http://www.guokr.com/blog/777525/
用Nim的方法来做加法运算
秘密就是把堆的大小用二进制数来表示(我假设读这篇文章的人都有一定的数学功底,只要稍微懂点电脑应该懂得二进制)。得到这个取胜秘密的取决于把堆的大小写成二进制形式,接着把这些数字加起来——但是别用一般的加法运算,准确的方法应该叫做Nim加法(Nim addition)。
为了准确的使用Nim加法加一些给定的二进制数,你先把它们排成行的写下来,就像你要做的加法运算一样。接着你轮流看每一列。如果1s的个数是奇数个,在它下面写一个1;如果偶数个,写个0.对每一列都进行这样的操作,得到的就是Nim加法的结果。
作为例子,让我们用Nim加运算加10,11和100(十进制下分别为2,3,4):
10
11
100
——
101
这个被称为Nim和(Nim sum)的结果是101。Nim加法和普通加法和普通加法不同在于:二进制的101表示十进制5,和原来那些数字之和2+3+4=9不相等。
谁赢了?
当Charles Bouton分析了这个Nim游戏,他分析出了两个两个取得获胜策略的关键事实。
事实一:假设轮到你行动了,这时堆里的Nim和为0。这样不管你怎么做,你动作后的Nim和不会等于0.
事实二:假设轮到你行动了,这时堆里的Nim和不为0。但是可以保证的是,存在一种取法能在你行动后的堆的Nim和为0。
其实nim加法等同于二进制加法中的【异或】操作。
题目是最简单的博弈论问题,解决方法是如果桌上石子能被4整除,则必输。如果桌上石子不能被4整除,则有必赢的策略。
class Solution { public: bool canWinNim(int n) { if(n%4==0) return false; else return true; } };
如果可以取得的最大数为m,则n%(m+1)为判断是否能赢的条件。
大牛写法为:
return n & 0x3;
之前的nim游戏是没有规定必须取多少个“石子”的,玩法是,放置3,4,5三列硬币,可以从某一列硬币中取走1~全部,最后拿走的人获胜。
关于这个的策略,人们发现从第一列3个硬币里取走2个,之后可以必胜。
取胜方法可以使用二进制来表示,并做nim加法,引用果壳的文章如下:
http://www.guokr.com/blog/777525/
用Nim的方法来做加法运算
秘密就是把堆的大小用二进制数来表示(我假设读这篇文章的人都有一定的数学功底,只要稍微懂点电脑应该懂得二进制)。得到这个取胜秘密的取决于把堆的大小写成二进制形式,接着把这些数字加起来——但是别用一般的加法运算,准确的方法应该叫做Nim加法(Nim addition)。
为了准确的使用Nim加法加一些给定的二进制数,你先把它们排成行的写下来,就像你要做的加法运算一样。接着你轮流看每一列。如果1s的个数是奇数个,在它下面写一个1;如果偶数个,写个0.对每一列都进行这样的操作,得到的就是Nim加法的结果。
作为例子,让我们用Nim加运算加10,11和100(十进制下分别为2,3,4):
10
11
100
——
101
这个被称为Nim和(Nim sum)的结果是101。Nim加法和普通加法和普通加法不同在于:二进制的101表示十进制5,和原来那些数字之和2+3+4=9不相等。
谁赢了?
当Charles Bouton分析了这个Nim游戏,他分析出了两个两个取得获胜策略的关键事实。
事实一:假设轮到你行动了,这时堆里的Nim和为0。这样不管你怎么做,你动作后的Nim和不会等于0.
事实二:假设轮到你行动了,这时堆里的Nim和不为0。但是可以保证的是,存在一种取法能在你行动后的堆的Nim和为0。
其实nim加法等同于二进制加法中的【异或】操作。
Nim加法 | ||
输入 | 输出 | |
1 | 1 | 1+1=0 |
1 | 0 | 1+0=1 |
0 | 1 | 0+1=1 |
0 | 0 | 0+0=0 |
相关文章推荐
- android Services
- 开启博客的第一天
- MySQL的主从复制与读写分离技术实例(一)主从复制
- python中input和raw_input用法及区别
- UITableView的分割线距左边有距离的解决办法
- BOOT Petalinux with JTAG
- MBProgressHUD(0.9.1)详解总结
- Leetcode 310. Minimun Height Trees使用set快速删除元素
- 带有指示器的自定义底部导航栏的实现
- linux syslog详解
- UVA 133(82)----The Dole Queue
- leetcode 202. Happy Number
- H5单页面架构:自定义路由 + requirejs + zepto + underscore
- LeetCode Copy List with Random Pointer
- 《JAVA与模式》学习之装饰模式
- UIKit框架(12)控制器view的生命周期方法
- Linux分区
- 关于屏幕常亮的问题
- android电池充电以及电量检测驱动分析
- 5分钟弄懂Docker!