“这是我参与8月更文挑战的第21天,活动详情查看:8月更文挑战”
关注我,以下内容持续更新
马踏棋盘(骑士周游问题)
马踏棋盘问题(骑士周游问题),是图的深度优先搜索(DFS)的应用.
- 马踏棋盘游戏规则
将马随机放在国际象棋的8×8棋盘Board[0~7][0~7]的某个方格中,马按走棋规则(马走日字)进行移动。要求每个方格只进入一次,走遍棋盘上全部64个方格
- 解决思想
马踏棋盘问题(骑士周游问题)实际上是图的深度优先搜索(DFS)的应用。可以使用回溯(就是深度优先搜索)来解决,假如马儿踏了53个点,发现已经走到尽头,没办法,那就只能回退了,查看其他的路径,就在棋盘上不停的回溯
- 解决步骤和思路
1) 创建棋盘chessBoard,是一个二维数组,值为0代表未走,值为1代表已走,定义两个数组ArrayRow和ArrayCol,分别代表马儿最多可以走的8个方向的x坐标和y坐标,注意ArrayRow和ArrayCol要一一对应来满足马走日的规则.
2) 假设马儿在(0,0)位置,因为第一个马儿已经放下,所以定义步数step=1,并将当前位置设置为已经访问,那么开始用for循环轮训尝试8个方向,判断是否未走并且未出界;
2.1)如果判断是,那么step+1,并标记为已走,如果step<64说明马儿未走完,那么递归放下一马儿;如果step=64,那么打印答案,并且return;
2.2)如果否,说明马儿的位置要拿走重新放,即回溯,让 step-1并且棋盘设置为未访问
注意:如果只想要一个答案,就在step=64的时候直接 return,如果想拿到所有的答案,那么就不必 return.请看代码标记①的位置
完整代码
#define m 6
#define n 6
int ArrayRow[]={-2 , -1 , 1 , 2 , 2 , 1 , -1 , -2};
int ArrayCol[]={-1 , -2 , -2 , -1 , 1 , 2 , 2 , 1};
int counter=0; //统计解的个数
int Board[m][n]={0};//棋盘,每一个初始化为0
//找解函数
void findAnswer(int x,int y,int step){
int aX=0,aY=0;//辅助
for(int i=0;i<8;i++){
aX=x+ArrayRow[i];
aY=y+ArrayCol[i];//考虑Board[aX][aY]
if(Board[aX][aY]==0&&aX<m&&aX>=0&&aY<n&&aY>=0)//未走过,且没有越界
{
step++;
Board[aX][aY]=step;//标上所走为第几步
if(step<m*n){
findAnswer(aX,aY,step);
}else{//找到一个解
printf("第%d\n",++counter);//解加1
printAnswer(Board);
return; //标记①
//如果把 return 注释就是查找所有的解,打开就是只拿到一个解
}
step--;
Board[aX][aY]=0;
}
}
}
void traverChessBoardCase()
{
int step=1;
int x=0,y=0;//开始坐标点
Board[x][y]=1;
findAnswer(x,y,step);//找解
}
//打印解
void printAnswer(int Array[m][n]){
int i,j;
for( i=0;i<m;i++){
for(j=0;j<n;j++){
printf("%3d ",Array[i][j]);
}
printf("\n\n");
}
}
复制代码
以(0,0)为起点的打印结果
1 8 31 28 15 20
6 27 16 21 32 29
9 2 7 30 19 14
26 5 12 17 22 33
3 10 35 24 13 18
36 25 4 11 34 23
复制代码
看了马踏棋盘问题的代码,你会发现它的思路和八皇后问题很相似(八皇后问题曾经讲过,有兴趣的小伙伴可以直接查看),可以借助这两个算法来理解递归算法
关注我
如果觉得我写的不错,请点个赞 关注我 您的支持是我更文最大的动力!