题目:
棋盘上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;
}