问题描述:在8*8方格的棋盘上,从任意指定的方格出发,为象棋中的马寻找一条走遍棋盘每一格并且只经过一次的一条路径(马走“日”字)。
1、马有8个方向可以行走,因此把八个方向用数组存储起来;
2、在主函数中,对每一个方格作为起点对整个棋盘进行回溯遍历;
3、在回溯过程中,要注意每一层的结尾对数据进行复原。
以下就是我按照这个思路写的算法,但是对于8*8的棋盘来说,效率极低!(对5*5的棋盘速度还算可以)。
#include <cstdio>
#include <cstdlib>
#include <memory.h>
using namespace std;
#define MAXLEN 8
int num;
bool flag[MAXLEN][MAXLEN];
int maxnum=MAXLEN*MAXLEN;
int dir[8][2]={
1, 2,
1, -2,
-1, 2,
-1, -2,
2, 1,
2, -1,
-2, 1,
-2, -1,
};
void DFS_search(int i,int j,int &count){
/*for(int p=0;p<MAXLEN;p++){
for(int q=0;q<MAXLEN;q++){
printf("%c ",flag[p][q]?21:22);
}
printf("\n");
}
printf("----------------------------------------------\n");
getchar();*/
if(count==maxnum){
num++;
return ;
}
for(int k=0;k<8;k++){
int ii=i+dir[k][0],jj=j+dir[k][1];
if(ii<MAXLEN&&ii>=0&&jj<MAXLEN&&jj>=0&&flag[ii][jj]==false){
flag[ii][jj]=true;
count++;
DFS_search(ii,jj,count);
count--;
flag[ii][jj]=false;
}
}
}
int main(){
int count;
num=0;
for(int i=0;i<MAXLEN;i++){
for(int j=0;j<MAXLEN;j++){
memset(flag,false,MAXLEN*sizeof(bool));
count=1;
flag[i][j]=true;
DFS_search(i,j,count);
}
}
printf("%d\n",num);
getchar();
return 0;
}
在一些网站上查了相关的资料,有人说需要在选择下一个方向的时候加上一个“启发式规则”,即选择了这个方向后,下一步可以选择的方向数最少!至于为什么这样做,也没有一个确切的说明,之后尝试成功之后再贴代码吧。
有知道最优解的朋友可以跟我讨论下哈,谢谢啦!