问题描述:
在中国象棋中,马只能走“日” 字。现有一5*4棋盘,马从位置(x,y)处出发,把棋盘的每一格都走一次,且只走一次。找出所有路径。
问题分析:
行n,列m,马在不出边界的情况下有8个方向可以行走(走日字),如当前坐标为(x,y),则行走后的坐标可以为:
(x+1,y+2) (x+1,y-2), (x+2,y+1) (x+2,y-1)
(x-1,y-2) (x-1,y+2) (x-2,y-1) (x-2,y+1)
算法设计:
搜索空间是整个棋盘n*m个棋盘上点
约束条件:不出边界且每个点只经过一次。
搜索过程:从任一点(x,y)出发,按深度优先的原则,从8个方向中尝试一个可以走的点,直到走过棋盘上所有n*m个点。
伪代码:
int fx[8]={1,2,2,1,-1,-2,-2,-1};
int fy[8]={2,1,-1,-2,-2,-1,1,2};
int n=5,m=4;
int a[5][4];
main() {
int i, j;
count = 0;
dep = 1;
print("请输入初始位置(x,y):");
input(x,y);
if (x > 5 or y > 4 or x < 1 or y < 1) { //判断输入是否合法
print("INPUT ERROR!");
return 0;
}
for (i = 1; i <= 5; i++) { //a[6][5]初始化置0,表示为遍历过该点
for (j = 1; j <= 4; j++)
a[i][j] = 0;
}
a[x][y] = 1; //起始点(x,y)的顺序为1
find(x, y, 2); //调用Path函数遍历下一点
if (count == 0) //输出走法数量
print("No Answer!");
else
print("共有%d种走法\n", count);
return 0;
}
find(int x,int y,int dep)
{
int i,xx,yy;
for(i=0;i<=8;i++)//8个方向试探
{
xx=x+fx[i];
yy=y+fy[i];
if(check(xx,yy=1))//判断新坐标
{
a[xx][yy]=dep;
if(dep==n*m)//当步数达到n*m时表示已走完每一个节点
{
count++;
output();
}
else
{
find(xx,yy,dep+1);//在新点上继续向下探索
}
a[xx][yy]=0;//回溯,将走过的点重置为未走过
}
}
}
Output() {
int i, j;
printf("第%d种走法\n", count);
for (i = 1; i < 6; i++) {
for (j = 1; j < 5; j++) {
print( a[i][j]);
}
print("\n");
}
print("\n");
}
c语言源代码:
# include<stdio.h>
int dep, x, y, count;
//dep为搜索的深度即已遍历的点数,(x,y)为初始坐标,count用于统计走法个数
int fx[8] = { 1,2,2,1,-1,-2,-2,-1 };
int fy[8] = { 2,1,-1,-2,-2,-1,1,2 };
int a[6][5];
//a[6][5]用于存储棋盘每一点,其值代表该点的遍历顺序,数组下标对应棋盘点的坐标
/*输出遍历结果*/
void Output_Path() {
int i, j;
printf("第%d种走法\n", count);
for (i = 1; i < 6; i++) {
for (j = 1; j < 5; j++) {
printf("%3d", a[i][j]);
}
printf("\n");
}
printf("\n");
}
/*遍历下一点,回溯*/
void Path(int x, int y, int dep) {
int i;
int xx, yy;
for (i = 0; i < 8; i++) { //(xx,yy)为下一步移动的新坐标
xx = x + fx[i];
yy = y + fy[i];
if (xx >= 1 && xx <= 5 && yy >= 1 && yy <= 4 && a[xx][yy] == 0) {
//判断新坐标(xx,yy)未出界且为被遍历过
a[xx][yy] = dep; //数组a存储当前点的遍历顺序
if (dep == 20) { //如果以全部遍历完则输出这种解法
count++;
Output_Path();
}
else {
Path(xx, yy, dep + 1); //没有遍历完则调用Path函数继续遍历下一点
}
a[xx][yy] = 0; //回溯,置0退回
}
}
}
int main() {
int i, j;
count = 0;
dep = 1;
printf("请输入初始位置(x,y):");
scanf("%d%d", &x, &y);
if (x > 5 || y > 4 || x < 1 || y < 1) { //判断输入是否合法
printf("INPUT ERROR!");
return 0;
}
for (i = 1; i <= 5; i++) { //a[6][5]初始化置0,表示为遍历过该点
for (j = 1; j <= 4; j++)
a[i][j] = 0;
}
a[x][y] = 1; //起始点(x,y)的顺序为1
Path(x, y, 2); //调用Path函数遍历下一点
if (count == 0) //输出走法数量
printf("No Answer!");
else
printf("共有%d种走法\n", count);
return 0;
}
运行截图: