GL游戏算法(附源码)
GL游戏规则:
有个列相当长的格子(格子总数不超过10的四次方),某些格子里面放了棋子(棋子总数足够多)
1.如果格子里面有棋子,就可以少拿走其中一颗,同时在这个格子的左边两个格子里面各放一颗;
2.如果连续两个格子里面都有棋子,可以分别从两个格子中都拿走一颗,并在她们右边的格子里面放入一颗
输入初始状态,反复使用规则1,2
输出终止状态(停机状态)
一. 每个格子至多只有一颗棋子
二. 相邻两个格子不能都有棋子
例如下图,格子里面的棋子数分别为为:2,3,5 ;终止状态为1, , ,1, , , , ,1
这是一道ACM的程序书上看到的一道题,当时书上面说的是用 斐波那契 数列来求解,此步骤简单,但是只能求得最后结果,不能得出每一步的步骤
笔者通过反复读取题意,根据题意想出一个算法,可以求得每一步的格局
具体算法如下:
第一个数为零
一。.第二个数>1
1。第三个数为零,则第二个数左移动 例如:0050 -> 1140
2。第三个数不为零
(1)第四个数为零,第二、三个数右移 例如:0520 ->0411
(2)第四个数不为零,第三、四个数右移动 例如:05220 ->05111 05221->05112
二。第二个数为1
. 1。第三个数为零,跳过本轮循环
. 2。第三个数不为零,
一直找到下一个不为1的数K
(1)数K为0,数k前两个数右移 例如:0111110 ->0111001
(2)数K大于1
1)数K下一个数为零,数K与其前一个数右移
例如:0111120 ->0111011 (2是K)
2)数K下一个数不为零
1*。数k下一个数的下一个数为零,数K与其下一个数右移
例如:0111121->01111101 (2是K)
2*。数K下一个数的下一个数不为零,
数K下一个数与其下一个数的下一个数右移
例如:011112130 ->011112021 (2是K)
对棋子数不断用以上方法,就可以得到最后要求的终止状态
相关代码:
01.#include"stdio.h"
02.#define M 40 //旗盘长度
03.#define N 20 //棋子放在旗盘的位置
04.int qi[M]; //存储每个格子里面的棋子
05.
06.void show() //显示当前状态下的棋子的格局
07.{
08. for (int i=0; i<M; i++)
09. if (qi[i] != 0)
10. printf("%d ",qi[i]);
11. else
12. printf("_ ");
13. printf("n");
14.}
15.
16.void yi_dong()
17.{
18. int temp = 1,biaoji = 0; //标记是否已经移动到最终状态
19. while (temp)
20. {
21. temp = 0;
22. for (int i=2; i 1) //第二个数大于1
26. {
27. if (qi[i+1] == 0)//第三个数为零,第二个数左移
28. {
29. qi[i-2]++;
30. qi[i-1]++;
31. qi[i]--;
32. }
33. else // 第三个数不为零
34. {
35. if(qi[i+2] == 0) //第四个数为零,第二,三个数右移
36. {
37. qi[i]--;
38. qi[i+1]--;
39. qi[i+2]++;
40. i = i + 2;
41. }
42. else //第四个数不为零,第三,四个数右移
43. {
44. qi[i+1]--;
45. qi[i+2]--;
46. qi[i+3]++;
47. i = i + 3;
48. }
49. }
50. show();
51. }//if (qi[i] > 1)
52. else if (qi[i] == 1) //第二个数为1
53. {
54. if(qi[i+1] == 0) //第三个数为零,跳过本轮循环
55. continue;
56. while (qi[i+1] == 1) //找到下一个不为1的数
57. i++;
58. if(i>M-2)
59. {
60. biaoji = 1;
61. break;
62. }
63. if(qi[i+1] == 0) //当下一个数i+1为零,则数i-1和i右移
64. {
65. qi[i-1]--;
66. qi[i]--;
67. qi[i+1]++;
68. i++;
69. }
70. else //当下一个数i+1大于1
71. {
72. if (i > M-5)
73. {
74. biaoji = 1;
75. break;
76. }
77. if (qi[i+2] == 0)//当下一个数的下一个数i+2为零,i与i+1右移
78. {
79. if (i > M-3)
80. {
81. biaoji = 1;
82. break;
83. }
84. qi[i]--;
85. qi[i+1]--;
86. qi[i+2]++;
87. i = i + 2;
88. }
89. else // 当下一个数的下一个数i+2不为零
90. {
91. if(qi[i+3] == 0) //当下一个数的下一个数的下一个数i+3为零,i+1与I+2右移
92. {
93. qi[i+1]--;
94. qi[i+2]--;
95. qi[i+3]++;
96. i = i + 3;
97. }
98. else //当下一个数的下一个数的下一个数不为零,i+2与i+3右移
99. {
100. qi[i+2]--;
101. qi[i+3]--;
102. qi[i+4]++;
103. i = i + 4;
104. }
105. }
106. }
107. show();
108. }//else if (qi[i] == 1)
109. }//for (int i=2; i<M-3; i++)
110. for (i=1; i0 || (qi[M-2]!=0 && qi[M-1]!=0) || biaoji ==1) //如果越界
113. {
114. printf("n此程序已经越界,请修改宏定义的 M 与 N 值后再运行该程序!n");
115. break;
116. }
117. if(qi[i]>1 || ((qi[i]==1 && qi[i-1]!=0) || (qi[i] == 1 && qi[i+1]!=0))) //如果到达终止状态
118. {
119. temp = 1;
120. break;
121. }
122. }
123.
124. }//while (temp)
125.}
126.
127.int main()
128.{
129. int chang; //存储棋子的总长度
130. for(int i=0; i<M; i++) //先个旗盘上每个棋子初始化为零
131. qi[i] = 0;
132. printf("请输入棋子所占格子的总长度:");
133. scanf("%d",&chang);
134. printf("分别输入每个棋子用空格隔开:n");
135. for (i=0; i<chang; i++)
136. scanf("%d", &qi[i+N]);
137. printf("格子的初始状态为:n");
138. show();
139. yi_dong();
140. getchar();getchar();getchar();
141. return 0;
142.}
相关截图: