迷宫路径的求解(非递归方法和递归方法)
来源:互联网 发布:旅行 知乎 编辑:程序博客网 时间: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;}
阅读全文
1 0
- 迷宫路径的求解(非递归方法和递归方法)
- !采用递归和非递归方法求解F(n)
- (递归+非递归)迷宫求解
- 采用递归和非递归方法求解汉诺塔问题
- 递归和栈求解迷宫的最短路径
- 路径条数 (迷宫问题的递归方法)
- 用递归和非递归的方法求解n的k次方
- 全排列(非递归和递归的方法)
- 迷宫问题递归与非递归求解
- 程序2.1:非递归方法实现迷宫
- 斐波那契数列的递归与非递归求解方法&递归的优缺点
- 汉诺塔递归方法和非递归方法
- 非递归求解汉诺塔的两种方法
- 迷宫求解非递归 DFS BFS(应用栈和队列)
- 二元树中和为某一值的所有路径(递归与非递归的方法)
- 递归改非递归的一般方法(二叉树前序的递归改非递归说起)
- 用递归和非递归的方法 逆置单链表
- 链表合并的递归和非递归方法
- 内存分配:堆、栈、全局变量/静态变量、代码区
- IE浏览器无法连接网络的解决办法
- VB脚本:SecureCRT中监控断言与异常方法
- C语言---柔性数组
- Github基本操作
- 迷宫路径的求解(非递归方法和递归方法)
- Webpack 3.0.0
- 新书《MyBatis 从入门到精通》
- gcc编译C++程序
- python -- 类处理与模块
- ACdream 1106 游泳水平有限的瑶瑶 (计算几何)(点到直线的最短距离)
- 有关send() / recv()函数的理解
- 快速浮点开方运算
- Swing 学习二 数据库篇