题目描述:有一天,小熊去玩迷宫,结果迷路了。小牛知道后,立即去解救小熊。现在小牛要以最短的速度去解救小熊。
迷宫由n行m列的单元格组成(n、m都小于等于50)每个单元格要么是空地,要么是障碍物,你的任务是帮助小牛找到一条从迷宫的起点通往小熊所在地的最短路径。(障碍物不能走、也不能走出迷宫)
思路:首先我们可以用一个二维数组来存这个迷宫,刚开始的时候,小牛在迷宫入口(1,1),小熊在(p,q)。其实就是找(1,1)到(p,q)的最短路径。但是小牛应该往右走还是往下走?
如果我们有两个小牛,一个往右走,一个往下走就好了。但是我们现在只有一个小牛,所以只能一个一个去尝试。我们先让小牛往右走,走不通再回到这里,尝试另外一个方向。(这里规定一个顺序,按照顺时针方向尝试:右、下、左、上)
我们可以看到,小牛一步之内可以达到的点只有(1,2)和(2,1)。根据规定,小牛先往右走,来到(1,2)这个点,来到(1,2)这个点后,小牛又可以达到的新的点为(2,2)。因为(1,3)是障碍物无法达到,(1,1)是刚才来的路径中已经走过的点(不能重复走)。所以小牛还得继续往下走,知道无路可走或者找到小熊。此条路线不一定是最短的!!!所以我们需要把所有的可能性都尝试一遍,最后输出最短路径!!
现在我们尝试用深度优先搜索(DFS)来实现。dfs()的功能是解决当前位置应该怎么办。而小牛在某个点需要处理的是:先检查是否已经找到小熊(即到达小熊所在的位置),如果没有就找出下一步可以走的地方。函数只需要维护三个参数:当前这个点的x坐标、y坐标以及当前已经走过的步数step
判断是否达到小哈的位置,以及是否是所用步数最少的走法只需要在函数里面添加判断语句即可
int dfs(int x,int y,int step){
if(x==p && y==q){//判断是否达到小熊的位置
if(stem<min){//判断是否是最短路径
min = step;
}
return ;//一旦找到了小熊的位置,就要返回
}
}
如果没有找到,就要按照以下方向走:
int next[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
//按照右下左上的顺序走
int k;
for(k=0;k<=3;k++){
tx = x + next[k][0];//x是当前位置的横坐标,是dfs函数传进去的,加上的是按照顺时针变化的话,x将如何变化,tx = 原来传入的x的值,加上按顺时针变化时x的取值变化。得到tx为下一步的横坐标
ty = y + next[k][1];//ty同理
}
接下来就是对tx,ty进行判断,同时用一个tool[tx][ty]数组记录(tx,ty)是否已经在路径中走过一次如果走过,tool[tx][ty],否则为0。同时也要判断tx和ty是否越界
如果tx,ty符合要求,就对这个点继续扩展,此时step+1。
代码实现如下:
for(k=0;k<=3;k++){
//计算下一个点的坐标
tx = x+next[k][0];
ty = y+next[k][1];
//判断是否越界
if(tx<1 || ty<1 || tx>n || ty>m){
continue;
}
if( a[tx][ty]==0 && tool[tx][ty]==0 ){
took[tx][ty] = 1; //标记这个点已经走过
dfs(tx,ty,step+1); //开始尝试下一个点
tool[tx][ty]=0; //这个点尝试结束后,取消标记,因为不一定第一次就能找到最短路径
}
}
完整代码如下:
#include<stdio.h>
int n,m,p,q,min=9999999;
int a[51][51],tool[51][51];
int dfs(int x,int y,int step){
int next[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};//按照右下左上走
int tx,ty,k;
if(x==p && y==q){
//判断是否到达小熊的位置
if(step < min)
//更新最小值
min = step;
return ;
}
for(k=0;k<=3;k++){
//计算下一个点的坐标
tx = x + next[k][0];
ty = y + next[k][1];
if(tx<1 || tx>n || ty<1 || ty>m)
continue;
//判断是否为障碍物或者已在路径中
if(a[tx][ty]==0 && tool[tx][ty]==0){
tool[tx][ty] = 1;
dfs(tx,ty,step+1);
tool[tx][ty]=0;
}
}
return ;
}
int main(){
int i,j,startx,starty;
scanf("%d %d",&n,&m); //输入n和m,n行m列
//创建迷宫
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%d",&a[i][j]);
//读入起点和终点坐标
scanf("%d%d%d%d",&startx,&starty,&p,&q);
tool[startx][starty] = 1; //标记起点已经在路径中,防止后面重复走
dfs(startx,starty,0);//第一个参数是起点的x坐标,第二个是起点的y坐标,第三个是初始步数0
printf("%d",min);//输出最短步数
}