国际象棋中马的周游路线问题的递归算法 程序问题
#include<stdio.h>
int H[8][8] = {0}; //全局变量的二维数组,用以保存马走步的放置情况,其中每个元素存放走步的序号,
//初值为0
int P[8][8] = {0}; //全局变量的二维数组,对应于棋盘上各个位置可以选择的位置数,即邻接点的度
struct D {
int x;
int y;
}DIR[8];
void go(int x,int y,int i) {
int min,j,u,v,u1,v1,m,n;
if(i == 65) { //递归出口,若棋盘上的每个位置都走过一遍,则算法结束
for(m = 0;m < 8;m++)
{
printf("\n");
for(n = 0;n < 8;n++)
printf("%5d",H[m][n]);
}
}
else {
min = 8;
for(j = 0;j < 8;j++) {
u = x + DIR[j].x;
v = y + DIR[j].y;
if((u >= 0) && (u < 8) && (v >= 0) && (v < 8) && (H[u][v] == 0)) {
//判断所走的位置是否超出棋盘应有位置
P[u][v] = P[u][v] - 1; //其邻接点的度减一。
if(P[u][v] < min) {
min = P[u][v];
u1 = u;
v1 = v;
}
}
}
H[u1][v1] = i;
go(u1,v1,i+1);//用满足条件的新顶点作为起点,继续递归调用
}
}
int main(void) {
int m,n;
printf("**********马得周游路线*********");
printf("说明:以下面的模拟棋盘为例:\n");
for(m = 0;m < 8;m++) {
printf("\n");
for(n = 0;n < 8;n++)
printf("%d%d ",m,n);
}
printf("\n\n请输入马得当前位置:");
scanf("%d,%d",&m,&n);
printf("\n");
H[m][n] = 1;
go(m,n,2);
printf("\n");
return 0;
}
大虾们请帮我看看,程序哪里出了点问题啊?
[解决办法]
先不谈算法就go函数里面u1,v1没有初始化就使用 程序必死
[解决办法]
楼主,很认真的看了你的代码,大概理解了你的意思,但是你的实现却令人难以理解,尤其这里定义的全局变量 P 和 局部变量 min,实在不明白它们的意义。 下面给出一个和楼主类似的实现,里面有详细的注释:
#include<stdio.h>// 注: 当为 8*8 的棋盘时,运行非常慢,在我电脑上要将近10分钟// 可以用较小的数据测试,如 7*7 ,6*6 或 6*7等#define R 8 // 棋盘的行数 #define C 8 // 棋盘的列数#define N (R*C+1) // 最大序号+1int H[R][C] = {0}; // 全局变量的二维数组,用以保存马走步的放置情况 // 其中每个元素存放走步的序号,初值为0bool g_just_find_one = false; // 标示是否只找一个走法,还是所有的bool g_find_solution = false; // 标示是否找到了走法// 位于[x,y]位置的马,需要检测 8 个方向来确定下一个位置, 如下图:// // 2 3 方向1: [x-1,y-2]; 方向2: [x-2,y-1];// 1 4 方向3: [x-2,y+1]; 方向4: [x-1,y+2];// H<---------[x,y] 方向5: [x+1,y+2]; 方向6: [x+2,y+1];// 8 5 方向7: [x+2,y-1]; 方向8: [x+1,y-2];// 7 6 注:x 为行,y 为列,探测方向:1-8 struct D { // 通过结构体来定义 8 个方向 int x; int y;}DIR[8] = { {-1,-2}, {-2,-1}, {-2,1}, {-1,2}, // 方向:1,2,3,4 {1,2}, {2,1}, {2,-1}, {1,-2} // 方向:5,6,7,8 };void go(int x,int y,int i) { // 搜索第 i 步的位置 int j,u,v,m,n; if (g_just_find_one) { // 如果只找一个走法 if(g_find_solution) { return; } } if(i == N) { // 递归出口,若棋盘上的每个位置都走过一遍,则算法结束 g_find_solution = true; for(m = 0;m < R;m++) { printf("\n"); for(n = 0;n < C;n++) printf("%5d",H[m][n]); } printf("\n\n\n"); } else { // 每一步都探测8个方向来确定下一个位置 for(j = 0;j < 8;j++) { u = x + DIR[j].x; v = y + DIR[j].y; if( (u >= 0) && (u < R) && // 行方向合法性判断 (v >= 0) && (v < C) && // 列方向合法性判断 (H[u][v] == 0) ) { // 是否可走判断 H[u][v] = i; // 位置合法,将该位置设置为当前步的序号 go(u,v,i+1); // 从当前位置走下一步 H[u][v] = 0; // 上一个方向探测结束后,将探测过的位置复位 // 以进行下一个方向的探测 } } }}int main(void) { int m,n; char ch; printf("**********马得周游路线*********"); printf("说明:以下面的模拟棋盘为例:\n"); for(m = 0;m < R;m++) { printf("\n"); for(n = 0;n < C;n++) printf("%d%d ",m,n); } printf("\n\n请输入马的当前位置,格式:x,y (其中 0=<x<%d, 0=<y<%d):",R,C); scanf("%d,%d",&m,&n); while (m<0 || m>R || n<0 || n>C) { printf("\n\n你的输入有误!"); printf("\n\n请输入马得当前位置,格式:x,y (其中 0=<x<%d, 0=<y<%d):",R,C); scanf("%d,%d",&m,&n); } getchar(); printf("\n\n是否只要求一个解法(Y 或 y 表示是,其它键表示否):"); scanf("%c",&ch); if (ch == 'Y' || ch == 'y') { g_just_find_one = true; } printf("\n"); H[m][n] = 1; go(m,n,2); printf("\n"); if (!g_find_solution) { printf("\n\n从输入点 (%d, %d) 开始,没有可行的路径!", m, n); } return 0;}// 输出示例:/***********马得周游路线*********说明:以下面的模拟棋盘为例:00 01 02 03 04 05 06 0710 11 12 13 14 15 16 1720 21 22 23 24 25 26 2730 31 32 33 34 35 36 3740 41 42 43 44 45 46 4750 51 52 53 54 55 56 5760 61 62 63 64 65 66 6770 71 72 73 74 75 76 77请输入马的当前位置,格式:x,y (其中 0=<x<8, 0=<y<8):2,0是否只要求一个解法(Y 或 y 表示是,其它键表示否):y 9 2 11 16 25 4 13 64 18 21 8 3 12 15 26 5 1 10 17 20 7 24 63 14 42 19 22 55 50 61 6 27 57 54 43 34 23 36 49 62 44 41 56 51 60 33 28 31 53 58 39 46 35 30 37 48 40 45 52 59 38 47 32 29请按任意键继续. . .*/
[解决办法]