初次编辑时间:2010-05-06
一、思路:此问题是搜索累。
1、深度优先:可以得到所有路径。既可以用递归算法,也可以用非递归算法。
2、广度优先:可以得到一条最短路径,并统计步数。
二、代码:
1、//迷宫问题-递归算法1-深搜-可显示所有路径
#include<stdio.h>
#define STATUS int
#define N 20
#define OK 1
#define ERROR 0
typedef struct
{
int x,y; //在迷宫中的位置
}Pt;
int step,ct,n,m; //步数,可行路线总数,地图尺寸,
int mazemap[N][N]; //迷宫地图
Pt start,end,st[N*N]; //入口,出口,额外辅助内存空间
const int a[8][2]={{-1,-1},{0,-1},{1,-1},{-1,0},{1,0},{-1,1},{0,1},{1,1}};
STATUS DFS(int x,int y);//递归深度优先搜索,寻找可行路径,所求路径均为简单路径
STATUS PrintPath(void); //打印路径
int main()
{
int i,j,k,t=1;
while(t)
{
printf("请输入迷宫的大小(长:m>0和宽:n>0):");
scanf("%d%d",&m,&n);
if(m<=0||n<=0||m>=N||n>=N)
{
printf("迷宫大小输入不合法!\n");
continue;
}
printf("请输入迷宫地图(-1表示该位置为不可通,0表示该位置可通):\n");
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)scanf("%d",&mazemap[i][j]);
start.x=start.y=1;end.x=m;end.y=n;ct=step=0;st[step]=start;
if(mazemap[start.x][start.y]==-1||mazemap[end.x][end.y]==-1)ct=0;
else {mazemap[start.x][start.y]=-1;DFS(start.x,start.y);}
printf("对这个迷宫,所有可通路径的总数为:%d\n",ct);
printf("如果要退出程序,请输入整数0,否则输入整数1 :");
scanf("%d",&t);
}
return 0;
}
STATUS DFS(int x,int y)
{
int i,x1,y1;
if(x==end.x&&y==end.y){ct++;PrintPath();return OK;}
for(i=0;i<8;i++)
{
x1=x+a[i][0];y1=y+a[i][1];
if(x1>=1&&x1<=m&&y1>=1&&y1<=n&&mazemap[x1][y1]==0)
{
step++;st[step].x=x1;st[step].y=y1;mazemap[x1][y1]=-1;
DFS(x1,y1);
step--;mazemap[x1][y1]=0; //回溯处理
}
}
return OK;
}
STATUS PrintPath()
{ //在屏幕上显示一条可行路径,包含入口和出口
int i;
if(step==0)printf("入口与出口重合!\n");
printf("第%-5d条可行路径:\n",ct);
printf("X Y 步数\n");
for(i=0;i<=step;i++)
printf("%-5d%-5d%-5d\n",st[i].x,st[i].y,i);
return OK;
}
2、//
迷宫问题
-
非递归算法
2-
深搜
-
可显示所有路径
#include<stdio.h>
#define N 20
#define STATUS int
#define OK 1
#define ERROR 0
typedef struct
{
int x,y; //在迷宫中的位置
int di; //记录下一步的方向
}Pt;
int step,ct,n,m; //步数,可行路线总数,地图尺寸,
int mazemap[N][N]; //迷宫地图
Pt start,end,st[N*N]; //入口,出口,额外辅助内存空间
const int a[8][2]={{-1,-1},{0,-1},{1,-1},{-1,0},{1,0},{-1,1},{0,1},{1,1}};
STATUS MazePath(void); //非递归深度优先搜索,寻找可行路径,所求路径均为简单路径
STATUS PrintPath(void); //打印路径
int main()
{
int i,j,k,t=1;
while(t)
{
printf("请输入迷宫的大小(长:m>0和宽:n>0):");
scanf("%d%d",&m,&n);
if(m<=0||n<=0||m>=N||n>=N)
{
printf("迷宫大小输入不合法!\n");
continue;
}
printf("请输入迷宫地图(-1表示该位置为不可通,0表示该位置可通):\n");
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)scanf("%d",&mazemap[i][j]);
start.x=start.y=1;start.di=-1;
end.x=m;end.y=n;ct=step=0;st[step]=start;
if(mazemap[start.x][start.y]==-1||mazemap[end.x][end.y]==-1)ct=0;
else MazePath();
printf("对这个迷宫,所有可通路径的总数为:%d\n",ct);
printf("如果要退出程序,请输入整数0,否则输入整数1 :");
scanf("%d",&t);
}
return 0;
}
STATUS MazePath()
{
int i=0,x1,y1;
mazemap[start.x][start.y]=-1;//入口已经入栈
while(step>=0)
{
if(st[step].x==end.x&&st[step].y==end.y)
{
ct++;
PrintPath();
mazemap[st[step].x][st[step].y]=0;
step--;
if(step<0)return OK;
}
for(i=st[step].di+1;i<8;i++)
{
x1=st[step].x+a[i][0];y1=st[step].y+a[i][1]; //下一步可能走的位置
if(x1>=1&&x1<=m&&y1>=1&&y1<=n&&mazemap[x1][y1]==0)
{
st[step].di=i; //更新方向
step++;st[step].x=x1;st[step].y=y1;st[step].di=-1;//新位置入栈
mazemap[x1][y1]=-1; //标记一走位置
break;
}
}
if(i>7){mazemap[st[step].x][st[step].y]=0;step--;}
}
return OK;
}
STATUS PrintPath()
{ //在屏幕上显示一条可行路径,包含入口和出口
int i;
if(step==0)printf("入口与出口重合!\n");
printf("第%-5d条可行路径:\n",ct);
printf("X Y 步数\n");
for(i=0;i<=step;i++)
printf("%-5d%-5d%-5d\n",st[i].x,st[i].y,i);
return OK;
}
3、//迷宫问题-非递归算法3-广搜-打印一条最短路径
#include<stdio.h>
#define STATUS int
#define N 20
#define OK 1
#define ERROR 0
typedef struct
{
int x,y,ft; //在迷宫中的位置,该位置的上一个位置对应下标
}Pt;
int n,m; //地图尺寸,
int mazemap[N][N]; //迷宫地图
Pt start,end,st[N*N]; //入口,出口,额外辅助内存空间
const int a[8][2]={{-1,-1},{0,-1},{1,-1},{-1,0},{1,0},{-1,1},{0,1},{1,1}};
STATUS BFS(void);//广度优先搜索,寻找最短可行路径,若路径存在返回OK,否则返回ERROR
STATUS PrintPath(int t); //打印路径
int main()
{
int i,j,k,t=1;
while(t)
{
printf("请输入迷宫的大小(长:m>0和宽:n>0):");
scanf("%d%d",&m,&n);
if(m<=0||n<=0||m>=N||n>=N)
{
printf("迷宫大小输入不合法!\n");
continue;
}
printf("请输入迷宫地图(-1表示该位置为不可通,0表示该位置可通):\n");
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)scanf("%d",&mazemap[i][j]);
start.x=start.y=1;start.ft=0;st[0]=start;end.x=m;end.y=n;
if(mazemap[start.x][start.y]==-1||mazemap[end.x][end.y]==-1||!BFS())
printf("对该迷宫,不存在可通路径!\n");
printf("如果要退出程序,请输入整数0,否则输入整数1 :");
scanf("%d",&t);
}
return 0;
}
STATUS BFS()
{
int i,f=0,r=0,x1,y1;
mazemap[1][1]=-1;
while(f<=r)
{
if(st[f].x==end.x&&st[f].y==end.y){PrintPath(f);return OK;}
for(i=0;i<8;i++)
{
x1=st[f].x+a[i][0];y1=st[f].y+a[i][1];
if(x1>=1&&x1<=m&&y1>=1&&y1<=n&&mazemap[x1][y1]==0)
{
r++;st.x=x1;st.y=y1;st.ft=f;//为了输出路径,故作此处理
mazemap[x1][y1]=-1;
}
}
f++;
}
return ERROR;
}
STATUS PrintPath(int t)
{ //在屏幕上显示一条可行路径,包含入口和出口
int i,k,a[N*N];
printf("对这个迷宫,存在最短路径:\n");
if(t==0)printf("入口与出口重合!\n");
for(i=0;t!=0;t=st[t].ft,i++)a[i]=t; //记录路径上各个位置在st中的下标
a[i]=t;
printf("X Y 步数\n");
for(k=0;i>=0;k++,i--)
printf("%-5d%-5d%-5d\n",st[a[i]].x,st[a[i]].y,k);
return OK;
}
三、测试数据:
1、
3 3
0 -1 0
-1 0 0
-1 -1 0
2、
4 5
0 -1 0 0 -1
0 0 -1 0 -1
-1 0 0 -1 0
0 -1 0 0 0
四、运行结果:
程序一:3条,128条
程序二:3条,128条
五、解释:代码3在求路径时,有两种方法。其一、根据辅助数组st[],利用队列信息,从而得出路径,st[f].ft域用来存放路径中位置f的前一步的位置,从而在搜索结束后利用此信息构造出路径。其二、可以利用迷宫地图mazemap[i][j]来记录访问路径,当位置(i,j)入队列时,置mazemap[i][j]的值为上一步到达(i,j)时所走的方向(共八个方向),从而在搜索结束后利用此信息构造路径。本代码中利用第一种方法构造路径。