迷宫路径的求解(非递归方法和递归方法)

来源:互联网 发布:旅行 知乎 编辑:程序博客网 时间:2024/05/18 00:33

迷宫路径的求解(非递归方法和递归方法)

(对于非递归 求解一条通路即可,这里借助了pre[ ][ ]数组记录前驱)

(非递归的辅助栈为链栈)


代码示例

#include<bits/stdc++.h>using namespace std;const int maxn=1000;const int dx[5]={0,0,1,0,-1};const int dy[5]={0,1,0,-1,0};struct Point{    int x,y;};typedef struct Snode{    Point data;    struct Snode *next;}Snode,*Linkstack;//链栈void initstack(Linkstack &S){    /*链栈初始化,有头结点*/     S=(Linkstack)malloc(sizeof(Snode));    S->next=NULL;}bool emptystack(Linkstack S){    /*判断链栈是否为空*/    if(S->next==NULL) return true;else return false;}void push(Linkstack &S,Point e){    //将一个数据e放入链栈    //头结点端为栈顶端     Linkstack p=(Linkstack)malloc(sizeof(Snode));    p->data=e;p->next=S->next;    S->next=p;}void pop(Linkstack &S,Point &e){    /*将栈顶弹出,保存在e中返回*/    if(S->next==NULL) return ;//栈为空     Linkstack p=S->next;    e=p->data;    S->next=p->next;    free(p);//释放空间 }int maze[maxn][maxn];//表示迷宫信息的二维数组char maze1[maxn][maxn];//辅助迷宫,最后由数组转字符用 bool visit[maxn][maxn];//dfs过程中判断某个位置是否已经访问过Point pre[maxn][maxn];//记录每个位置的前驱,用于非递归Point solution[maxn*maxn];//记录方案路径上的点 int m,n;//迷宫m行n列bool flag=0;//标记 void Input_maze(){    /*用二维数组读入迷宫信息*/    for(int i=1;i<=m;++i)        for(int j=1;j<=n;++j)            scanf("%d",&maze[i][j]);}void Output_maze(){    /*输出迷宫信息*/    printf("迷宫为:\n");    for(int i=1;i<=m;++i){        for(int j=1;j<=n;++j) printf("%d ",maze[i][j]);        printf("\n");    }    printf("\n");}int getdirection(Point a,Point b)//a为起点,b为终点 {    /*返回点x->点y的方向(保证x与y是相邻节点)*/    for(int i=1;i<=4;++i)        if(a.x+dx[i]==b.x&&a.y+dy[i]==b.y) return i;}void output1(){    /*以三元组形式输出任务一中的一条通路*/    int len=0;    Point p={m,n};//既然调用output1,则说明已能到m,n点,则从该点开始     while(!(p.x==1&&p.y==1))//这里相当于solution里存放从终点到起点     {//所经历的点的坐标,即先放进数组的是离终点进的点         solution[++len]={p.x,p.y};//利用pre给solution赋值         p=pre[p.x][p.y];    }    solution[++len]={1,1};//最后放起点     for(int i=len;i>=2;--i)//从起点(len位置)开始,根据solution相邻点打印方向     {        printf("(%d,%d,%d)->",solution[i].x,solution[i].y,getdirection(solution[i],solution[i-1]));    }    printf("(%d,%d,0)\n\n",m,n);}bool check(Point u){    /*判断在搜索过程中一个点u是否可以到达(包括是否是障碍节点以及是否已经遍历过)*/    return maze[u.x][u.y]==0&&!visit[u.x][u.y]&&u.x>=1&&u.y>=1&&u.x<=m&&u.y<=n;}void solve1()//非递归模拟dfs {    /*求出(1,1)->(n,m)的一条通路*/    printf("任务1:\n\n");    Linkstack S;//指向头结点的指针     initstack(S);    push(S,{1,1});    memset(visit,0,sizeof(visit));    visit[1][1]=1;    while(!emptystack(S))//非空     {        Point u;        pop(S,u);//取出栈顶        if(u.x==m&&u.y==n){//判断是否已经到达终点,如果到达就输出该组解            output1();            return;        }        for(int i=1;i<=4;++i)//四方向扩展        {            Point v;            v.x=u.x+dx[i];v.y=u.y+dy[i];            if(!check(v)) continue;//这个方向不满足条件             visit[v.x][v.y]=1;            pre[v.x][v.y]=u;//该点的前驱结点为u//主要是因为非递归的DFS不能直接带着第几步的参数//所以借用pre二维数组,不断更新每一个点的前驱点//也可以在Point结构体中加上计数器(类似BFS)             push(S,v);//新的节点入栈        }    }    printf("没有通路!\n\n");//while过程结束都没有返回则说明无解}void output2(int len){    /*以点阵形式输出所有通路*/    for(int i=1;i<=m;++i)        for(int j=1;j<=n;++j)            maze1[i][j]=maze[i][j]+48;                for(int i=1;i<len;++i){//对路径上的len个点中前len-1个换成指向下一个点的方向         int x=solution[i].x;int y=solution[i].y;int d=getdirection(solution[i],solution[i+1]);        if(d==1) maze1[x][y]='>';//向右         if(d==2) maze1[x][y]='|';        if(d==3) maze1[x][y]='<';//向左         if(d==4) maze1[x][y]='|';    }    flag=1;//做个有解的标记    for(int i=1;i<=m;++i){//变换后直接输出         for(int j=1;j<=n;++j)            printf("%c ",maze1[i][j]);        printf("\n");    }    printf("\n");}void dfs(int k,int x,int y){    /*k表示当前走到第几步,x,y表示当前的位置*/    solution[k]={x,y};    visit[x][y]=1;    if(x==m&&y==n) output2(k);//如果到了终点就输出此方案    elsefor(int i=1;i<=4;++i)//四个方向遍历    {        int u=x+dx[i],v=y+dy[i];        if(!check({u,v})) continue;        dfs(k+1,u,v);    }        visit[x][y]=0;//回溯,visit信息清零}void solve2(){    /*求出(1,1)->(n,m)的所有通路*/    printf("任务2:\n\n");    flag=0;    memset(visit,0,sizeof(visit));    dfs(1,1,1);    if(!flag) printf("没有通路!\n\n");}int main(){    //freopen("C://Users//Francis//Desktop//mycode//read.txt","r",stdin);    int cas=0; while(scanf("%d%d",&m,&n)!=EOF)    {    memset(maze,0,sizeof(maze));    memset(visit,0,sizeof(visit));    cas++;    printf("Test %d:\n",cas);        Input_maze();        Output_maze();        solve1();        solve2();        printf("***********************************************************\n");    }    return 0;}


原创粉丝点击