问题描述
8*8的国际象棋棋盘上的一只马,恰好走过除起点外的其他63个位置各一次,最后回到起点。这条路线称为马的一条Hamiltion周游路线。对于给定的m*n的国际象棋盘,m,n均为大于5的偶数,且|m-n|<=2,试分析分治算法找出马的一条Hamilton周游路线。
算法设计
对于给定的偶数m,n>=6,且|m-n|<=2,计算m*n的国际象棋盘上马的一条Hamilton周游路线
此题求马的哈密顿周游路径,采用的方法是深度搜索的方法,深度搜索的思想是让马一直跑,假如遇到死胡同(无路可走)时就回退到上一个位置,在上一个位置重新走没有走过的路,直到找到终点为止,而这里的终点就是我们的起点位置。
解法思路有了,那我们该如何通过代码实现呢?
很明显,我们在寻找终点的途中有时会需要回退(遇到死胡同时),这样一个条件我们可以用递归来实现,通过分析,我们可以得出下面三种种情况:
1、找到终点并且走完了棋盘,成功,直接打印棋盘
2、没有找到终点,但是并未遇到死胡同,继续走(递归)
3、走到了死胡同,直接回退到上一个位置,尝试另外的走法
有了这三个分支条件,我们便能得出如下代码:
#include <iostream>
using namespace std;
//定义马的八种走法
int passX[8] = {-2,-1,1,2,-2,-1,2,1};
int passY[8] = {-1,-2,-2,-1,1,2,1,2};
//棋盘
int table[100][100] = {0};
int startX,startY;//起点位置
//棋盘规模
int m,n;
//判断下一步是否到达起点
int isEnd(int x,int y){
//判断下一个位置是否到达终点也需要对是否越界进行判断
int xx,yy;
for(int i = 0;i<8;i++){
xx = x + passX[i];
yy = y + passY[i];
if((xx<m&&xx>=0&&yy<n&&yy>=0)&& table[xx][yy] == 1){//下一步为1,是终点,返回1
return 1;
}
}
return 0;
}
//打印棋盘
void printTable(){
for(int i = 0;i<m;++i){
for(int j = 0;j<n;++j){
cout<<table[i][j]<<" ";
}
cout<<endl;
}
}
bool fun(int x,int y,int num){
//判断下一步是否为起点并且棋盘已经走满
if(num == m*n+1&&isEnd(x,y)){ //这里n*m需要加一是因为第一步(起点)为1,终点也是起点,所以起点被走了两次,故总步数需要加一
//找到终点,直接打印棋盘
printTable();
//返回true给上一个位置
return true;
}
//没有走到起点,继续往下走
int xx = 0,yy = 0;
for(int i = 0;i<8;++i){
//下一步走的位置
xx = x + passX[i];
yy = y + passY[i];
//判断下一步是否越界并且已经走过
if((xx<m&&xx>=0&&yy<n&&yy>=0) && (!table[xx][yy])){
//递归继续往下走
table[xx][yy] = num;
if(fun(xx,yy,num + 1))return true;//返回true给上一个位置
//回退,并把刚刚走的位置置为0,便于下次经过,继续循环寻找下一种走法
table[xx][yy] = 0;
}
}
//无路可走并且没有走回起点,回退到上一个位置去寻找另外的路
return false;
}
int main(){
cin>>m>>n;
//初始化起点
cin>>startX>>startY;
table[startX][startY]=1;//将起始位置为1,也就是第一步
fun(startX,startY,2);
return 0;
}
代码大致实现过程为:当输入一个位置,我们首先判断其下一个位置是否能够到达终点并且是否已经将棋盘走完,成立则返回true结束递归,不成交则进行下一步,这里马有八种走法,我们用了两个长度为8的数组来封装这八种走法,每次走下一步的时候需要把这八种走法遍历一遍,同时判断当前这种走法是否越界,然后进行递归到下一个位置进行同样的判断,当走到了死胡同(遍历八种走法都不能走)时,直接返回false,上一个位置接收到了false之后,需要对这一个位置做置0处理,以便于下一次继续走这个位置,然后尝试下一种走法,这样寻寻往复最终可以得到哈密顿路,这里提醒一下,在判断马的下一步是否到达终点时也需要做一次越界判断,(但是网上大佬的代码并没有进行判断也能成功运行,这里我也搞不懂为什么)否则会出错。
以上便是个人拙见,有错误望指出