华为机试--捡石子

来源:互联网 发布:一颗五角星的淘宝买家 编辑:程序博客网 时间:2024/06/05 04:32

昨天去华为机试,前两道都比较简单,最后一道是关于捡石子的问题,当时没想到好的办法解决,8个测试用例只过了6个,回来想了想,想到了一种能解决的方法。

题目:有n(n>=2)个石子,甲乙两个人从这些石子中轮流拿取m(m>=1)个石子,规定第一个拿的人可以拿任意多个,但不能完全拿完,然后,后面的人最多可以拿取前面人的2倍,最后一个拿完石子的人获胜。第一个获胜的人输出1,第二个人获胜输出2。

举例:一共有10个石子,甲先拿,那甲刚开始最少拿1个,最多拿9个(不能拿完)。假如甲拿2个,则乙最少拿1个,最多 拿4个(2的两倍)。若乙拿2个,则甲最少拿1个,最多拿4个。以此类推,直到一方把所有石子都拿完而获胜。

解析:虽然第一个人可以拿任意多个,但是后面的人最多可以拿他所拿石子的2倍,那么第一个人最多不能拿超过总数的1/3,等于1/3也不可以,必须小于1/3。后面的人也是如此。则两个人每次最多拿(n-1)/3,由于最少要拿一个,则每次最多拿 t=max{(remaining-1)/3,1},remaining为剩余石子数量。定义一个一维数组c[0...n](0,1位置不用),数组的第i个元素c[i]表示石子个数为i时胜出的一方(1或者2)。上面已经讲了,一方每次最多拿t=max{(remaining-1)/3,1}个,最少可以拿1个,则每次可以拿count={1...t}个。

讲到这差不多就知道怎么做了。如果现在剩余remaining个,现在拿石子的一方可以拿count(count=1...t)个,则此时拿完count个后,还剩余remaining-count个。由于之前数组c[] 已经保存了c[remaining-count]的大小,也就是胜出一方,则我们可以在remaining-1到remaining-t中寻找是否有2(因为此时代表后边的人先取,如果自己想要赢,寻找的数中必须有2),如果有,则先取的人会赢;否则,后取得人会赢。

0 0
原创粉丝点击