做这个题的时候,写了挺久,因为比较熟悉深搜,所以一下就想用深搜解题,但是题目不适合用这个深搜,因为不仅会重复搜索多次,还会因为数据较大而时间超限。
题目是这样的:
【题目描述】
有一个 n×m 的棋盘,在某个点 (x,y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。
【输入】
输入只有一行四个整数,分别为 n , m , x , y 。
【输出】
一个 n×m 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 −1)。
样例输入
3 3 1 1
样例输出
0 3 2
3 -1 1
2 1 4
题目很短,用广搜简单粗暴。但是还是想试试深搜,如果数字不大的话,深搜也可以实现,思路是这样:把每一个点(马当前的点(x,y)除外)都当做起点进行一遍深搜,听起来有点吓人,因为这样操作还要判断到达这点的最短路径是多少,就是说每个点的深搜都包括若干次比较,找出最小的路径,存入数组,一个点接着一个点的深搜,很复杂...
深搜解题代码如下:(但是过不了)
#include
int n,m,x0,y0;
int book[405][405],flag[405][405];
int min=99999999;
void fun(int x1,int y1,int step)
{
//记录方向数组,一共八个方向
int next[8][2]={2,1,-1,-2,-1,2,2,-1,1,2,1,-2,-2,1,-2,-1};
int i,tx,ty;
for(i=0;i<8;i++)
{
tx=x1+next[i][0];
ty=y1+next[i][1];
if(tx==x0&&ty==y0)
{
if(stepn||ty<=0||ty>m)
continue;
if(book[tx][ty]==0)
{
book[tx][ty]=1;
fun(tx,ty,step+1);
book[tx][ty]=0;//每一轮结束,取消标记
}
}
return ;
}
int main()
{
int i,j;
scanf("%d %d %d %d",&n,&m,&x0,&y0);
//将每一个点代入
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
//起点用book数组标记为 1
book[x0][y0]=1;
//如果该点是起点就不用深搜
if(i!=x0||j!=y0)
{
fun(i,j,1);
if(min<99999999)
flag[i][j]=min;
min=99999999;//每一个点深搜完,把 min 重新赋值,否则会出现多个数值相同的情况
int k,b;
for(k=0;k
解题思路
一个平平无奇的广搜,首先定义结构体,存放一个点的 x 值,y 值,step(步数)。
然后用入队的方式,把未经过的点加入,加入时统计步数,然后一步步出队,最后队空,未统计步数的就是不能到达的点,然后得到结果。
代码如下:
#include
struct node
{
int x;
int y;
int step;//存放走到这个点所用的步数
};
int book[405][405],flag[405][405],n,m;
int main()
{
int x0,y0,i,j;
//记录方向的数组
int next[8][2]={2,1,1,2,1,-2,2,-1,-1,2,-1,-2,-2,1,-2,-1};
struct node k[160005];
scanf("%d %d %d %d",&n,&m,&x0,&y0);
//将所有点认为是不能到达,全部赋值为 -1
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
flag[i][j]=-1;
}
int tx,ty,tail=1,head=1;
//将起点入队
k[tail].x=x0;
k[tail].y=y0;
k[tail].step=0;
//并标记起点,避免重复经过
book[x0][y0]=1;
tail++;
while(headn||ty<=0||ty>m)
continue;
//要满足:未出界且先前没有经过该点
if(book[tx][ty]==0)
{
//第一件事标记我来过
book[tx][ty]=1;
//然后入队
k[tail].x=tx;
k[tail].y=ty;
//到这点的步数就是:扩展到这点的队头步数(k[head].step)加上 1
k[tail].step=k[head].step+1;
//把算出来的步数存入数组
flag[tx][ty]=k[tail].step;
tail++;
}
}
head++;
}
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
//起点处输出为 0
if(i==x0&&j==y0)
printf("0 ");
else
printf("%-5d",flag[i][j]);
}
printf("\n");
}
return 0;
}
总结
广搜和深搜都各有优缺点,做题时要灵活运用,比如这题更适合用广搜bfs。
一般情况下,深度优先搜索法占内存少但速度较慢,广度优先搜索算法占内存多但速度较快,在距离和深度成正比的情况下能较快地求出最优解。