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

输出5*5棋盘的骑士周游的方法数:

#include<stdio.h>
#include<stdlib.h>

#define X 5
#define Y 5

int chess[X][Y]={{0}};//二维数组的初始化,两个大括号

int count=0;


void print()
{
    int i,j;
    for(i=0;i<X;++i)
    {
        for(j=0;j<Y;++j)
        {
            printf("%d ",chess[i][j]);
        }
        printf("\n");//这里的\n放置也非常巧妙,一行之后换行
    }
    printf("\n");//一趟走完也换一次行,亲测这个没必要换行,因为visit中已经有换行;用了也没事,就多一个换行而已

}

void visit(int x,int y,int tag)
{
    int i,j;
    i=x;
    j=y;
    chess[i][j]=tag;
    if(tag==X*Y)
    {
        printf("第%d方法:\n",++count);//这里有一个换行不要忘记了
        print();
    }
    /* 1、一只在中间的马,假如四周都可以走,那么他有八种走法;每个象限各两种; 2、用回溯法,每次递归哪个位置是随机的,取决于你安排的if的位置前后 3、有一个递归变量tag每次递增1,是用来判断当tag等于棋盘大小时,则算一次走完全盘 4、这里有个count全局变量也非常重要,是用来记录总共有多少个走法; 仔细体会体会count和tag的不同之处,都是递归加1,但是做法和作用不太一样 5、还有这里的X,Y也是属于全局变量,要注意理解 6、横纵坐标的问题,这里的数组象限判断出错了,i正负,表示上下移动,即行方向移动,不要和数学中的混淆; j正负,表示左右移动,即列方向移动, */
    //第一象限右一进二 第一象限进一右二
    if(i+1<X&&j+2<Y&&chess[i+1][j+2]==0)
    {
        visit(i+1,j+2,tag+1);
    }
    //第一象限右二进一 第一象限进二右一
    if(i+2<X&&j+1<Y&&chess[i+2][j+1]==0)
    {
        visit(i+2,j+1,tag+1);
    }
    //第二象限左一进二 第四象限退一右二
    if(i-1>=0&&j+2<Y&&chess[i-1][j+2]==0)
    {
        visit(i-1,j+2,tag+1);
    }
    //第二象限左二进一 第四象限退二右一
    if(i-2>=0&&j+1<Y&&chess[i-2][j+1]==0)
    {
        visit(i-2,j+1,tag+1);
    }
    //第三象限左一退二 第三象限退一左二
    if(i-1>=0&&j-2>=0&&chess[i-1][j-2]==0)
    {
        visit(i-1,j-2,tag+1);
    }
    //第三象限左二退一 第三象限退二左一
    if(i-2>=0&&j-1>=0&&chess[i-2][j-1]==0)
    {
        visit(i-2,j-1,tag+1);
    }
    //第四象限右一退二 第二象限进一左二
    if(i+1<X&&j-2>=0&&chess[i+1][j-2]==0)
    {
        visit(i+1,j-2,tag+1);
    }
    //第四象限右二退一 第二象限进二左一
    if(i+2<X&&j-1>=0&&chess[i+2][j-1]==0)
    {
        visit(i+2,j-1,tag+1);
    }
    /*这一步重置标记位置为0,也是相当重要,作用是让给下一种走法; 这个chess放在这里很巧妙,可能有点难理解:chess是放在所有八个递归函数的最后,也就是说,第一次 执行这个chess是第一个tag=X*Y,比如5*5就是25;然后从25开始,依次回退, 这里还有一个难点,就是这里是回溯法,所以更准确的说不是,从25开始依次回退到1;而是从25回退,让后再检测其他相邻结点; 有点像深度优先查询; */
    chess[i][j]=0;

}

int main()
{
    int n,l;
    printf("请输入棋盘的第一个落子位置坐标,空格分隔,横纵坐标都已0开始:");
    scanf("%d %d",&n,&l);
    //visit第一个参数为纵坐标,第二个参数为横坐标,第三个参数固定为1,因为这是第一次调用,横纵坐标从左上角0,0开始
    visit(n,l,1);
    return 0;
}
    原文作者:骑士周游问题
    原文地址: https://blog.csdn.net/happy_bigqiang/article/details/55054288
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞