石头游戏

来源:互联网 发布:淘宝装修热点 编辑:程序博客网 时间:2024/04/24 04:39

【座右铭】1. 想要成为行家,就必须尝试解决大量的问题;

                    2. 解决大量问题并不代表能解决所有问题,而是表示解决下一个问题的几率变大了


1.有65颗宝石,两个人来取,规则是每次必须且只能取1-3颗,取完后,手中为偶数颗的取胜,请编制一个先手必胜的取法程序【问题来源于论坛】

第一部分:思路

1.定义一个N*4的矩阵的矩阵:

 

1个石头

2个石头

3个石头

4个石头

[奇,奇]

(1,1)

(0,1)

(1,3)

(0,1)

 

[奇,偶]

(0,1)

(1,1)

(0,1)

(1,3)

 

[偶,奇]

(0,1)

(1,2)

(0,2)

(-1,1)

 

[偶,偶]

(-1,1)

(0,2)

(1,2)

(0,2)

 

第1列的二元组分别表示第一个人和第二个人在取石头之前手上的石头数。例如[奇,奇]表示第一个人手上为奇数个石头,第二个人手上为奇数个石头。

第2列的二元组分别表示第一个人是否获胜,以及如何取石头。例如(1,1)表示第一个人取1个石头肯定获胜;(0,1)表示最好的结局是平均,取1颗石头;(-1,1)表示第一个人肯定会输,取1颗石头

2.在初始化1、2、3个石头后,以后的胜负可依次推导出,例如:

设T(i,[奇,奇])表示二人在第i个石头(i>3)前,手上的石头数都为奇数,则有:

T(i,[奇,奇]) = max{-1*T(i-1,[奇,偶]),-1*T(i-2,[奇,奇]),-1*T(i-3,[奇,偶])},其中“-1*T(i-1,[奇,偶])”表示第一个人取了1个石头后,手上就有偶数个石头。轮到第二个人取时,就把第一个人和第二个人调换下,然后从矩阵的第i-1列获知胜负,然后将胜负再调换。

第二部分:Java代码,不考虑异常情况

public class Game {private Game(){}/** * 对外接口,返回N*4*2的矩阵 * @param number * 输入的石头数 * @return * 返回N*4*2的矩阵 */public static int[][][] start(int number){number = number>3?number:3;int[][][] path = new int[number+1][4][2];//初始化1颗石头path[1][0][0] = 1; path[1][0][1] = 1;path[1][1][0] = 0; path[1][1][1] = 1;path[1][2][0] = 0; path[1][2][1] = 1;path[1][3][0] = -1; path[1][3][1] = 1;//初始化2颗石头path[2][0][0] = 0; path[2][0][1] = 1;path[2][1][0] = 1; path[2][1][1] = 1;path[2][2][0] = 1; path[2][2][1] = 2;path[2][3][0] = 0; path[2][3][1] = 2;//初始化3颗石头path[3][0][0] = 1; path[3][0][1] = 3;path[3][1][0] = 0; path[3][1][1] = 1;path[3][2][0] = 0; path[3][2][1] = 2;path[3][3][0] = 1; path[3][3][1] = 2;for(int i=4;i<=number;i++){for(int j=0;j<4;j++){//拿1颗石头int p = exchange(j,1);path[i][j][0] = -1*path[i-1][p][0];path[i][j][1] = 1;//拿2颗石头p = exchange(j,2);int result = -1*path[i-2][p][0];if(result>path[i][j][0]){path[i][j][0] = result;path[i][j][1] = 2;}//拿3颗石头p = exchange(j,3);result = -1*path[i-3][p][0];if(result>path[i][j][0]){path[i][j][0] = result;path[i][j][1] = 3;}}}return path;}/* * 奇偶对调  */static int exchange(int index, int stone){//第一人的手上石头数发生改变if(stone==1||stone==3){switch(index){case 0:index=2;break;case 1:index=3;break;case 2:index=0;break;default: index=1;}}switch(index){case 0:return 0;case 1:return 2;case 2:return 1;default: return 3;}}}

第三部分:测试用例

在输入石头数为65时,结果如下所示:

[偶,偶]:-1 0 1 0 1 0 1 0 -1 0 1 0 1 0 1 0 -1 0 1 0 1 0 1 0 -1 0 1 0 1 0 1 0 -1 0 1 0 1 0 1 0 -1 0 1 0 1 0 1 0 -1 0 1 0 1 0 1 0 -1 0 1 0 1 0 1 0 -1 

从该序列中可知,当石头数为65时,先出手必败。而且还可从发现如下规律:

1)当石头数模8余1时,先手必败

2)当石头数模8余3,5,7时,先手必胜

3)当石头数模8余0,2,4,6时,平局

原创粉丝点击