机器博弈中的数据结构与基本方法(二)-----递归及回溯法实例
1、跳马问题:从左上角开始,按照象棋中马的行走规则(但是不考虑马脚,只需要按日字走),要求每个点走一次且仅一次,并且所有的点走走到,求解所有可行走法。

思路及代码:
1 #include <cstdio>
2 int a[9][9]; //包含边界拓展
3 int S = 0; //总的方案数
4 void PrintAnswer(){ //打印行走策略
5 printf("Answer\t%d\n", S);
6 for (int i = 2; i < 7; i++){
7 for (int j = 2; j < 7; j++){
8 printf("%-4d\t", a[i][j]);
9 }
10 printf("\n");
11 }
12 }
13 void Try(int i, int ml, int nl);
14 void Move(int i, int m, int n){
15 if (0 == a[m][n]){
16 a[m][n] = i;
17 if (i < 25){
18 Try(i+1, m, n);
19 } else {
20 S++;
21 PrintAnswer();
22 }
23 a[m][n] = 0;
24 }
25 }
26 void Try(int i, int ml, int nl){ //i:到达结点编号,ml/nl出发点的位置
27 int n, m;
28 m = ml - 2;
29 n = nl + 1; //走法 1
30 Move(i, m, n);
31
32 m = ml - 2;
33 n = nl - 1; //走法 2
34 Move(i, m, n);
35
36 m = ml + 2;
37 n = nl + 1; //走法 3
38 Move(i, m, n);
39
40 m = ml + 2;
41 n = nl - 1; //走法 4
42 Move(i, m, n);
43
44 m = ml - 1;
45 n = nl + 2; //走法 5
46 Move(i, m, n);
47
48 m = ml - 1;
49 n = nl - 2; //走法 6
50 Move(i, m, n);
51
52 m = ml + 1;
53 n = nl + 2; //走法 7
54 Move(i, m, n);
55
56 m = ml + 1;
57 n = nl - 2; //走法 8
58 Move(i, m, n);
59 }
60 int main(int argc, char const *argv[])
61 {
62 freopen("ans.txt", "w", stdout);
63 for (int i = 0; i < 9; i++){
64 for (int j = 0; j < 9; j++){
65 if (i < 2 || i > 6 || j < 2 || j > 6){
66 a[i][j] = -1;
67 } else {
68 a[i][j] = 0;
69 }
70 }
71 }
72 a[2][2] = 1;
73 Try(2, 2, 2);
74 return 0;
75 }
ans.cpp
部分答案
1 Answer 301
2 1 6 17 12 25
3 16 11 2 7 18
4 3 20 5 24 13
5 10 15 22 19 8
6 21 4 9 14 23
7 Answer 302
8 1 16 7 12 25
9 8 13 2 17 6
10 3 20 15 24 11
11 14 9 22 5 18
12 21 4 19 10 23
13 Answer 303
14 1 18 7 12 25
15 8 13 2 19 6
16 3 20 17 24 11
17 14 9 22 5 16
18 21 4 15 10 23
19 Answer 304
20 1 8 19 14 25
21 18 13 2 9 6
22 3 20 7 24 15
23 12 17 22 5 10
24 21 4 11 16 23
25 共 304 种策略
部分答案
图示

2、迷宫问题:如下图,求出所有可以到达出口的路径(左上角绿色是入口,右下角是出口,深红色部分是墙,红色是为了编程方便(边界判断)人为加的)。

代码及思路
1 #include <cstdio>
2 int a[8][12];
3 int s = 0;
4 void PrintPath(){
5 printf("Path%d\n", s);
6 for (int i = 1; i < 7; i++){
7 for (int j = 1; j < 11; j++)
8 {
9 printf("%4d", a[i][j]);
10 }
11 printf("\n");
12 }
13 }
14 void Try(int i, int ml, int nl);
15 void Move(int i, int m, int n){
16 if (0 == a[m][n]){
17 a[m][n] = i;
18 if (6 == m && 10 == n){
19 s++;
20 PrintPath();
21 } else {
22 Try(i+1, m, n);
23 }
24 a[m][n] = 0;
25 }
26 }
27
28 void Try(int i, int ml, int nl){
29 int m, n;
30 m = ml;
31 n = nl - 1; //注意只能上下左右与移动
32 Move(i, m, n);
33
34 m = ml;
35 n = nl + 1;
36 Move(i, m, n);
37
38 m = ml - 1;
39 n = nl;
40 Move(i, m, n);
41
42 m = ml + 1;
43 n = nl;
44 Move(i, m, n);
45 }
46 int main(int argc, char const *argv[])
47 {
48 freopen("ans.txt", "w", stdout);
49 for (int i = 0; i < 8; i++){
50 for (int j = 0; j < 12; j++){
51 a[i][j] = -1;
52 }
53 }
54 a[1][1] = 0;
55 for (int i = 1; i <= 8; i++){
56 if (2!=i && 5!=i){
57 a[2][i] = 0;
58 }
59 }
60 for (int i = 1; i <= 9; i++){
61 if (4!=i && 5!=i && 7!=i){
62 a[3][i] = 0;
63 }
64 }
65 for (int i = 1; i <= 9; i++){
66 if (2!=i && 3!=i && 7!=i && 8!=i){
67 a[4][i] = 0;
68 }
69 }
70 for (int i = 1; i <= 9; i++){
71 if (5!=i){
72 a[5][i] = 0;
73 }
74 }
75 a[6][9] = a[6][10] = 0;
76 a[1][1] = 1;
77 Try(2, 1, 1);
78 printf("Sum = %d\n", s);
79 return 0;
80 }
ans.cpp
输出结果
Path1
1 -1 -1 -1 -1 -1 -1 -1 -1 -1
2 -1 0 0 -1 13 14 15 -1 -1
3 0 0 -1 -1 12 -1 16 17 -1
4 -1 -1 9 10 11 -1 -1 18 -1
5 6 7 8 -1 0 0 0 19 -1
-1 -1 -1 -1 -1 -1 -1 -1 20 21
Path2
1 -1 -1 -1 -1 -1 -1 -1 -1 -1
2 -1 0 0 -1 0 0 0 -1 -1
3 0 0 -1 -1 0 -1 0 0 -1
4 -1 -1 9 10 11 -1 -1 0 -1
5 6 7 8 -1 12 13 14 15 -1
-1 -1 -1 -1 -1 -1 -1 -1 16 17
Sum = 2
输出结果
图示

