10马踏棋盘之中国象棋

题目:在半个中国象棋棋盘上,马在左下角(1,1)处,马走日字,而且只能往右走,不能向左,可以上下,求起点到(m,n)处有几种不同的走法。

基本思想:递归回溯探索算法

测试数据:
9 5 37
8 4 20
3 2 1
4 4 2

/* 题目:在半个中国象棋棋盘上,马在左下角(1,1)处,马走日字,而且只能往右走,不能向左,可以上下,求起点到(m,n)处有几种不同的走法。 基本思想:递归回溯探索算法 算法: 1。存储棋盘(二维数组) 2。 测试数据: 9 5 37 8 4 20 3 2 1 4 4 2 ***** 总之对应的规则是:数组横坐标对应数学横坐标,数组纵坐标对应数学纵坐标; 关键记忆点就是一个二维数组的第一参数是纵坐标,第二参数是横坐标,起点在左上方0.0 ***** */
#include<stdio.h>
#include<stdlib.h>

#define X 5
#define Y 9

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 x1,int y1)
{
    int i,j;
    i=x;
    j=y;
    chess[i][j]=tag;
    if(x==x1&&y==y1)
    {
        printf("第%d方法:\n",++count);//这里有一个换行不要忘记了
        print();
    }
    /* 1、要非常小心这里的二维数组的横纵坐标和数学中的横纵坐标的理解: 数组的横坐标,即X,表示的是矩阵的行数,数组的纵坐标,即Y,表示的是矩阵的列数;非常非常容易混淆;因为 数学中的横坐标,小x是表示矩阵的列数;数学中的纵坐标,即小y,表示的是矩阵的行数,刚刚好相反; 2、还是横纵坐标的问题,这里的数组象限判断出错了,i正负,表示上下移动,即行方向移动,不要和数学中的混淆; j正负,表示左右移动,即列方向移动 */
    //第一象限进一右二
    if(i+1<X&&j+2<Y&&chess[i+1][j+2]==0)
    {
        visit(i+1,j+2,tag+1,x1,y1);
    }
    //第一象限进二右一
    if(i+2<X&&j+1<Y&&chess[i+2][j+1]==0)
    {
        visit(i+2,j+1,tag+1,x1,y1);
    }
    ////第四象限退一右二
    if(i-1>=0&&j+2<Y&&chess[i-1][j+2]==0)
    {
        visit(i-1,j+2,tag+1,x1,y1);
    }
    //第四象限退二右一
    if(i-2>=0&&j+1<Y&&chess[i-2][j+1]==0)
    {
        visit(i-2,j+1,tag+1,x1,y1);
    }
    /*这一步重置标记位置为0,也是相当重要,作用是让给下一种走法; 这个chess放在这里很巧妙,可能有点难理解:chess是放在所有八个递归函数的最后,也就是说,第一次 执行这个chess是第一个tag=X*Y,比如5*5就是25;然后从25开始,依次回退, 这里还有一个难点,就是这里是回溯法,所以更准确的说不是,从25开始依次回退到1;而是从25回退,让后再检测其他相邻结点; 有点像深度优先查询; */
    chess[i][j]=0;

}

int main()
{
    int n,l;
    //因为数组的横纵坐标是从矩阵的左上角的0,0开始,而题目要求是从左下角的1,1开始所以要转换;
    int x2,y2;
    printf("请输入棋盘的最后的落子位置坐标,空格分隔,棋盘横纵坐标从左下方1,1开始:");
    scanf("%d %d",&n,&l);

    x2=X-l;//注意这里的转换是数组的X对应数学的y
    y2=n-1;
    //printf("%d%d",x2,y2);
    //visit 第一参数是起点的数组纵坐标,第二参数是起点的数组横坐标,第三参数是落子的标记,第四参数是最后落子的纵坐标
    //第五参数是最后落子的横坐标;
    visit(X-1,0,1,x2,y2);
    return 0;
}
    原文作者:骑士周游问题
    原文地址: https://blog.csdn.net/happy_bigqiang/article/details/55105678
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞