数据结构与算法九:经典算法面试题--4.马踏棋盘

837 阅读3分钟

这是我参与8月更文挑战的第21天,活动详情查看:8月更文挑战

关注我,以下内容持续更新

数据结构与算法(一):时间复杂度和空间复杂度

数据结构与算法(二):桟

数据结构与算法(三):队列

数据结构与算法(四):单链表

数据结构与算法(五):双向链表

数据结构与算法(六):哈希表

数据结构与算法(七):树

数据结构与算法(八):排序算法

数据结构与算法(九):经典算法面试题

马踏棋盘(骑士周游问题)

 马踏棋盘问题(骑士周游问题),是图的深度优先搜索(DFS)的应用.

  1. 马踏棋盘游戏规则

 将马随机放在国际象棋的8×8棋盘Board[0~7][0~7]的某个方格中,马按走棋规则(马走日字)进行移动。要求每个方格只进入一次,走遍棋盘上全部64个方格

  1. 解决思想

 马踏棋盘问题(骑士周游问题)实际上是图的深度优先搜索(DFS)的应用。可以使用回溯(就是深度优先搜索)来解决,假如马儿踏了53个点,发现已经走到尽头,没办法,那就只能回退了,查看其他的路径,就在棋盘上不停的回溯

  1. 解决步骤和思路

 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

看了马踏棋盘问题的代码,你会发现它的思路和八皇后问题很相似(八皇后问题曾经讲过,有兴趣的小伙伴可以直接查看),可以借助这两个算法来理解递归算法

关注我

如果觉得我写的不错,请点个赞 关注我 您的支持是我更文最大的动力!