回溯法--马挡卒子

题目:

       棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:
可以向下、或者向右。同时在棋盘上C点有一个对方的马,
该马所在的点和所有跳跃一步可达的点称为对方马的控制点。
因此称之为”马拦过河卒”。
棋盘用坐标表示,A点(0, 0)、B点(n, m)(n, m为不超过16的整数),
同样马的位置坐标是需要给出的。现在要求你计算出卒从A点能够到达B点的路径的条数,
假设马的位置是固定不动的,并不是卒走一步马走一步。

思路:

      本题很自然就可以想到采用回溯法求解。回溯法在求解网格类算法问题是有效的。具体求解时,先根据马的位置标记卒子不能到达的位置(马行日),在当前位置下,如果向右可以移动,则递归向右移动,如果向下可以移动,则递归向下移动,如果到达目标,则终止递归。需要注意的是,利用递归来表达回溯法是很自然的。因为回溯法是深度优先的,递归也是。

程序源代码如下:

#include “stdlib.h”
#include “stdio.h”
 
static int path[30] = {0};/*记录路径,值为1表示向右,值为2表示向下16*2-2=30*/
int pathNum = 0;/*记录路径长度*/
static int mesh[16][16] = {0};/*16*16棋盘*/
int Bx,By,Cx,Cy;/*记录B,C的位置,A的位置为(0,0)*/
   
/*设置马的控制位置*/
void SetConfig ()
{
    /*判断C的位置是否合法*/
    if (Cx<0 && Cx>15 && Cy<0 && Cy>15)
        printf(“The location of C is wrong !/n”);
       
    /*分析马的控制位置并在棋盘标记*/   
    mesh[Cx][Cy] = 1;
    if (Cy >= 2)
    {
        if (Cx >= 1)
            mesh[Cx-1][Cy-2] = 1;
        if (Cx <= 14)
            mesh[Cx+1][Cy-2] = 1;
    }
    if (Cy <= 13)
    {
        if (Cx >= 1)
            mesh[Cx-1][Cy+2] = 1;
        if (Cx <= 14)
            mesh[Cx+1][Cy+2] = 1;
    }
    if (Cx >= 2)
    {
        if (Cy >= 1)
            mesh[Cx-2][Cy-1] = 1;
        if (Cy <= 14)
            mesh[Cx-2][Cy+1] = 1;
    }
    if (Cx <= 13)
    {
        if (Cy >= 2)
            mesh[Cx+2][Cy-1] = 1;
        if (Cy <= 13)
            mesh[Cx+2][Cy+1] = 1;
    }
}

/*打印路径*/
void PrintPath(int p)
{
    printf(“Path %d is as followed:/n”, pathNum);
    int k = 0;
    for (k=0; k<p; k++)
    {
        if (path[k] == 1)
            printf(“right “);
        if (path[k] == 2)
            printf(“down “);
    }
    printf(“/n/n”);
}

/*递归搜索*/
void DoRecureSearch (int i, int j)
{
    if (mesh[i][j] == 2)/*达到B点*/
    {
        pathNum++;
        PrintPath(i+j);
        return;
    }
   
    if (i<Bx && mesh[i+1][j]!=1)/*向右扩展*/
    {
        path[i+j] = 1;
        DoRecureSearch(i+1, j);
    }
   
    if (j<By && mesh[i][j+1]!=1)/*向下扩展*/
    { 
        path[i+j] = 2;
        DoRecureSearch(i, j+1);
    }
}

/*搜索*/
void Search ()
{
    /*判断B的位置是否合法*/
    if (Bx<0 && Bx>15 && By<0 && By>15)
    {
        printf(“The location of C is wrong !/n”);
        return;
    }
   
    /*判断B的位置是否在马的控制位置中*/
    if (mesh[Bx][By] == 1)
    {
        printf(“The B is never reached !/n”);
        return;
    }

    if (mesh[0][0] == 1)
    {
        printf(“The A is never begin !/n”);
        return;
    }
    
    mesh[Bx][By] = 2;/*标记终点位置*/
    /*打印棋盘及A,B,C的位置*/
    int i,j;
    for (i=0; i<16; i++)
    {
        for (j=0; j<16; j++)
        {
            if (i==Bx && j==By)
                printf(“B “);
            else if (i==0 && j==0)
                printf(“A “);
            else if (mesh[i][j] == 1)
                printf(“C “);
            else
                printf(“0 “);
        }
        printf(“/n”);
    }   
   
    /*递归形式求解*/
    DoRecureSearch(0, 0);
    printf(“There is %d paths/n”, pathNum);
}

int main ()
{
    /*获取输入*/
    printf(“Please input the location of B/n”);
    scanf(“%d”, &Bx);
    scanf(“%d”, &By);
    printf(“Please input the location of C/n”);
    scanf(“%d”, &Cx);
    scanf(“%d”, &Cy);
   
    /*求解并打印*/
    SetConfig();
    Search();
    system(“pause”);
    return 0;
}
 

    原文作者:回溯法
    原文地址: https://blog.csdn.net/zrjdds/article/details/2139667
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞