迷宫求解

初次编辑时间: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)时所走的方向(共八个方向),从而在搜索结束后利用此信息构造路径。本代码中利用第一种方法构造路径。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值