任务简述
设计非递归算法,根据入口和出口位置将给定迷宫中的全部可行路线输出,并标记出其中的最短路径;
int mg[10][10]={
{1,1,1,1,1,1,1,1,1,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,0,0,1,1,0,0,1},
{1,0,1,1,1,0,0,0,0,1},
{1,0,0,0,1,0,0,0,0,1},
{1,0,1,0,0,0,1,0,0,1},
{1,0,1,1,1,0,1,1,0,1},
{1,1,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1},
}; //该二维数组表示迷宫,0表示可行,1表示不可行。
算法描述
用temp将矩阵复制一份,先对temp操作,利用队列dd求出最短路径的长度,若存在路径,则再对mg操作,利用栈T求出所有与最短路径长度一样的路径并输出。
源代码
#include "stdio.h"
#include "stdlib.h"
#define N 8
typedef struct ddd{
int x,y,pre;
}dd;//队列
typedef struct mystack{
int xx[100],yy[100];
int fangxiang[100];
int top;
}ST;//栈
int dx[4]={0,0,-1,1};//四个方向的改变
int dy[4]={-1,1,0,0};
int mg[10][10]={
{1,1,1,1,1,1,1,1,1,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,0,0,1,1,0,0,1},
{1,0,1,1,1,0,0,0,0,1},
{1,0,0,0,1,0,0,0,0,1},
{1,0,1,0,0,0,1,0,0,1},
{1,0,1,1,1,0,1,1,0,1},
{1,1,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1},
}; //迷宫
void showway(ST T,int n);
int main(){
int start_x,start_y,end_x,end_y;
printf("请输入起点、终点的坐标:");
scanf("%d%d%d%d",&start_x,&start_y,&end_x,&end_y);
int head=1,tail=1,flag=0,i,j,tx,ty,minlen=0,temp[10][10];//head,tail分别表示队头和队尾,flag用来判断是否存在路径,i用来循环四个方向,tx,ty用来记录位置,minlen表示最短路径的长度,用temp将矩阵复制,找最短路径的操作对temp进行
dd d[100]; //队列
for(i=0;i<10;i++) for(j=0;j<10;j++) temp[i][j]=mg[i][j];
d[1].x=start_x,d[1].y=start_y,d[1].pre=0,temp[start_x][start_y]=1;//设置起点的数据
while(head<=tail&&tail<100){//先找出最短路径的长度
if(d[head].x==end_x&&d[head].y==end_y){//head达到终点,由于tail可能一次大不止一个,所以用head
while(head){
minlen++;
head=d[head].pre;
}
flag=1;
printf("最短要%d步\n",minlen);
break;
}
for(i=0;i<4;i++){//四个方向循环,判断是否能走
tx=d[head].x+dx[i];
ty=d[head].y+dy[i];
if(temp[tx][ty]==0){//判断是否能走
tail++;
d[tail].x=tx;
d[tail].y=ty;
d[tail].pre=head;
temp[tx][ty]=1;//将这个点变为1
}
}
head++;
}
if(flag==0)//如果不存在路径
printf("no way\n");
else{//若存在路径,则输出所有最短路径
ST T;//栈
int nextpose=0,tiaoshu=0;//用nextpose判断下一步的方向,条数记录路径条数
T.top=0;//初始化栈的数据
T.xx[0]=1;
T.yy[0]=1;
mg[1][1]=1;
while(T.top>=0){
for(i=nextpose;i<4;i++){//四个方向
if(i>=4) break;//如果进来时便i>=4则break
tx=T.xx[T.top]+dx[i];
ty=T.yy[T.top]+dy[i];
if(mg[tx][ty]==0){//当前方向可行
T.fangxiang[T.top]=i;//记下当前方向
if(tx==end_x&&ty==end_y){//已经到了终点
tiaoshu++;
if(T.top==minlen-2){//top还未++且从0开始,所以top=minlen-2时路径长度为最短路径的长度,输出该路径并tiaoshu++
printf("下面为一条最短路径:\n");
}
T.top++;
T.xx[T.top]=tx;
T.yy[T.top]=ty;
T.top--;
showway(T,T.top+2);
printf("路径长度:%d\n",T.top+2);
mg[T.xx[T.top]][T.yy[T.top]]=0;//将当前点更改为可行并top--,对前一个点进行下一个方向的操作
T.top--;
nextpose=T.fangxiang[T.top]+1;
break;
}
else{
mg[tx][ty]=1;//将当前点更改为不可行并计入栈中,之后对这个点的四个方向进行操作
T.top++;
T.xx[T.top]=tx;
T.yy[T.top]=ty;
nextpose=0;
break;
}
}
}
if(i>=4){//若当前点四个方向都不可行,则弹栈并开始对前一个点进行操作
mg[T.xx[T.top]][T.yy[T.top]]=0;
T.top--;
nextpose=T.fangxiang[T.top]+1;
}
}
printf("共%d条\n",tiaoshu);
}
return 0;
}
void showway(ST T,int n){//显示路径的函数,n为路径长度
int i,j;
for(i=0,j=0;i<n;i++){
printf("(%d,%d) ",T.xx[i],T.yy[i]);
j++;
if(j%10==0)
printf("\n");
}
printf("\n\n");
}//共121行
运行结果
总结
队列可以用来找出最短路径,栈则可类似递归地找出所有路径,两种数据结构一起使用可以找出所有的最短路径。老师上课的时候提示了这种做法,下来自己尝试了一下便成功了。在使用指针前要记得给指针赋初值。