迷宫求解问题资料

合集下载

数据结构课程设计迷宫问题求解

数据结构课程设计迷宫问题求解

数据结构课程设计迷宫问题求解正文:一、引言在数据结构课程设计中,迷宫问题求解是一个经典且常见的问题。

迷宫问题求解是指通过编程实现在迷宫中找到一条从起点到终点的路径。

本文将详细介绍如何用数据结构来解决迷宫问题。

二、问题分析1.迷宫定义:迷宫是由多个格子组成的矩形区域,其中包括起点和终点。

迷宫中的格子可以是墙壁(无法通过)或者通道(可以通过)。

2.求解目标:在给定的迷宫中,找到从起点到终点的一条路径。

3.输入:迷宫的大小、起点坐标、终点坐标以及墙壁的位置。

4.输出:从起点到终点的路径,或者提示无解。

三、算法设计1.基础概念a) 迷宫的表示:可以使用二维数组来表示迷宫,数组的元素可以是墙壁、通道或者路径上的点。

b) 坐标系统:可以使用(x, y)来表示迷宫中各个点的坐标。

c) 方向定义:可以用上、下、左、右等四个方向来表示移动的方向。

2.深度优先搜索算法(DFS)a) 算法思想:从起点开始,沿着一个方向一直走到无法继续为止,然后回退到上一个点,再选择其他方向继续探索。

b) 算法步骤:i) 标记当前点为已访问。

ii) 判断当前点是否为终点,如果是则返回路径;否则继续。

iii) 遍历四个方向:1.如果该方向的下一个点是通道且未访问,则继续向该方向前进。

2.如果该方向的下一个点是墙壁或已访问,则尝试下一个方向。

iv) 如果四个方向都无法前进,则回退到上一个点,继续向其他方向探索。

3.广度优先搜索算法(BFS)a) 算法思想:从起点开始,逐层向外探索,直到找到终点或者所有点都被访问。

b) 算法步骤:i) 标记起点为已访问,加入队列。

ii) 循环以下步骤直到队列为空:1.取出队首元素。

2.判断当前点是否为终点,如果是则返回路径;否则继续。

3.遍历四个方向:a.如果该方向的下一个点是通道且未访问,则标记为已访问,加入队列。

iii) 如果队列为空仍未找到终点,则提示无解。

四、算法实现1.选择合适的编程语言和开发环境。

迷宫问题算法

迷宫问题算法

迷宫问题算法一、引言迷宫问题是一个经典的算法问题,对于寻找路径的算法有着广泛的应用。

迷宫是一个由通路和墙壁组成的结构,从起点出发,要找到通往终点的路径。

迷宫问题算法主要解决的是如何找到一条从起点到终点的最短路径。

二、DFS(深度优先搜索)算法深度优先搜索算法是迷宫问题求解中最常用的算法之一。

其基本思想是从起点开始,沿着一个方向不断向前走,当走到无法继续前进的位置时,回退到上一个位置,选择另一个方向继续前进,直到找到终点或者无路可走为止。

1. 算法步骤1.初始化一个空栈,并将起点入栈。

2.当栈不为空时,取出栈顶元素作为当前位置。

3.如果当前位置是终点,则返回找到的路径。

4.如果当前位置是墙壁或者已经访问过的位置,则回退到上一个位置。

5.如果当前位置是通路且未访问过,则将其加入路径中,并将其邻居位置入栈。

6.重复步骤2-5,直到找到终点或者栈为空。

2. 算法实现伪代码以下为DFS算法的实现伪代码:procedure DFS(maze, start, end):stack := empty stackpath := empty listvisited := empty setstack.push(start)while stack is not empty docurrent := stack.pop()if current == end thenreturn pathif current is wall or visited.contains(current) thencontinuepath.append(current)visited.add(current)for each neighbor in getNeighbors(current) dostack.push(neighbor)return "No path found"三、BFS(广度优先搜索)算法广度优先搜索算法也是解决迷宫问题的常用算法之一。

数据结构迷宫求解

数据结构迷宫求解

数据结构迷宫求解迷宫问题是一种常见的求解问题,通过在迷宫中找到从起点到终点的路径。

在计算机科学中,使用数据结构来解决迷宫问题非常方便。

本文将介绍迷宫问题的基本原理、常见的求解方法以及使用不同数据结构的优缺点。

首先,我们需要明确迷宫的基本定义。

迷宫可以看作是一个二维的网格,其中包含一些墙壁和通路。

起点是迷宫的入口,终点则是迷宫的出口。

我们的目标是找到从起点到终点的一条路径。

迷宫问题可以使用多种算法求解,包括深度优先(DFS)、广度优先(BFS)、最短路径算法等。

以下将详细介绍这些算法以及它们在迷宫问题中的应用。

同时,我们还会讨论不同数据结构在求解迷宫问题中的优缺点。

首先,深度优先(DFS)是一种常用的求解迷宫问题的算法。

该算法从起点开始,一直到终点,期间遇到墙壁或已经访问过的点则回溯到上一个节点。

DFS可以使用递归实现,也可以使用栈来保存需要回溯的节点。

DFS的优点是简单易懂,易于实现。

然而,它可能会陷入死循环或者找到一条较长的路径而不是最短路径。

另一种常见的算法是广度优先(BFS),它从起点开始,逐层扩展,直到找到终点为止。

BFS可以使用队列来保存每一层的节点。

与DFS相比,BFS能够找到最短路径,但它需要维护一个较大的队列,从而增加了空间复杂度。

除了DFS和BFS,还有一些其他算法可以应用于迷宫问题。

例如,迪杰斯特拉算法和A*算法可以找到最短路径。

这些算法使用了图的概念,将迷宫中的通道表示为图的边,将各个节点之间的距离表示为图的权重。

然后,通过计算最短路径的权重,找到从起点到终点的最短路径。

迪杰斯特拉算法和A*算法的优点是能够找到最短路径,但它们的实现较为复杂。

在使用这些算法求解迷宫问题时,我们需要选择适合的数据结构来存储迷宫和过程中的状态。

以下是几种常见的数据结构以及它们的优缺点:1.数组:数组是一种常见的数据结构,它可以用来表示迷宫。

可以使用二维数组来表示迷宫的网格,并使用特定的值表示墙壁和通路。

迷宫求解

迷宫求解
int line; //line表示“列”号
}PosType; //位置的元素类型
这样判断其可通与否的语句为
if (maze[CurPos.row][CurPos.line]==0)
1.迷宫的初始化
void Initmaze(int maze[12][12],int size); //初始化迷宫
迷宫的初始化有两种方法,一是随即生成,一是手动设置,由用户选择。随即生成的方法是程序生成随机数,除以2取余
maze[i][j]=rand()%2;
手动设置是用户输入0,1由程序读取
尺寸大小size可以设置,但是不能超过10,因为二维数组第一行,最后一行,第一列,最后一列一定要是不可通的,这是算法中用到的一个技巧。
迷宫内通道块位置变量类型定义为PosType
typedef struct
{
int row; //row表示“行”号
{
Markfoot(maze,curpos); // 留下足迹
e.di =1;
e.ord = curstep;
e.seat= curpos;
Push(S,e); // 加入路径
一、上机实验的问题和要求:迷宫问题(书P50 3.2.4和《数据结构题集》P105 2.9):以一个m×n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。设计一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。
利用链栈结构,然后编写一个求解迷宫的非递归程序。求得的通路以三元组(i,j,d)的形式输出,其中:(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。如:对于下列数据的迷宫,输出的一条通路为:(1,1,1),(1,2,2),(2,2,2),(3,2,3),….。

实验3 迷宫求解

实验3      迷宫求解

实验3 迷宫求解一、实验目的学会建立迷宫,在迷宫中寻找任意两坐标间是否存在路径,显示出该路径。

并熟练应用“栈”。

二、实验内容1、在计算机中用0、1图表示迷宫,0和1分别表示迷宫中的通路和障碍。

所求路径必须是简单路径,即在求得的路径上不能重复出现同一通道。

假设“当前位置”指的是“在搜索过程中的某一时刻所在图中某个位置”,则求迷宫中一条路径的算法的基本思想是:若当前位置“可通”,则纳入“当前路径”,并继续朝“下一位置”探索,即切换“下一位置”为“当前位置”,如此重复直至到达出口;若当前位置“不可通”,则应顺着“来向”退回到“前一通道”,然后朝着除“来向”之外的其他方向继续探索;若该通道块的四周4个方向均“不可通”,则应从“当前路径”上删除该通道。

所谓“下一位置”指的是当前位置四周4个方向(东、南、西、北)“1”。

假设以栈S记录“当前路径”,则栈顶中存放的是“当前路径上最后一个通道”。

由此,“纳入路径”的操作即为“当前位置入栈”;“从当前路径上删除前一通道”的操作即为“出栈”。

若当前位置可通,则纳入当前路径,并继续朝下一个位置探索,即切换下一位置为当前位置,如此重复直至到达出口;若当前位置不可通,则应顺着来向退回到前一通道块,然后朝着除来向之外的其他方向继续探索;若该通道块的四周4个方块均不可通,则应从当前路径上删除该通道块.设以栈记录当前路径,则栈顶中存放的是当前路径上最后一个通道块.由此,纳入路径的操作即为当前位置入栈;从当前路径上删除前一通道块的才操作即为出栈.2、求迷宫中一条从入口到出口的路径的算法可简单描述如下:设顶当前位置的初值为入口位置;Do{若当前位置可通,则{ 将当前位置插入栈顶; //纳入通路若该位置是出口位置,则结束; //求得路径存放在栈中否则切换当前位置的东邻方块为新的当前位置;}否则,若栈不空切栈顶位置尚有其他方向未经探索,则设定新的当前位置为沿顺时针方向旋转找到的栈顶位置的下一相邻块;若栈不空但栈顶位置的四周均不可通;则{ 删去栈顶位置; //从路径中删除该通道块若栈不空,则重新测试新的栈顶位置,直至找到一个可通的相邻块或出栈至栈空}}while(栈不空);3、数据结构设计考虑1) 创建一个Int类型的二维数组Maze(i,j),用来存放0和1 ;创建一个堆栈,用来存储当前路径2) 创造一个栈包括(*top表示栈顶,*base表示栈基址,stackSize表示栈容量)堆栈中每个空间包括(ord表示当前位置在路径上的序号,seat表示当前坐标,di表示往下一坐标的方向)当前坐标包括(r表示行,c表示列)4、主要采取三大模块:主程序模块、栈模块和迷宫模块算法设计一、栈模块:实现迷宫数据的抽象化和对迷宫数据的处理。

迷宫问题的求解(回溯法、深度优先遍历、广度优先遍历)

迷宫问题的求解(回溯法、深度优先遍历、广度优先遍历)

迷宫问题的求解(回溯法、深度优先遍历、⼴度优先遍历)⼀、问题介绍 有⼀个迷宫地图,有⼀些可达的位置,也有⼀些不可达的位置(障碍、墙壁、边界)。

从⼀个位置到下⼀个位置只能通过向上(或者向右、或者向下、或者向左)⾛⼀步来实现,从起点出发,如何找到⼀条到达终点的通路。

本⽂将⽤两种不同的解决思路,四种具体实现来求解迷宫问题。

⽤⼆维矩阵来模拟迷宫地图,1代表该位置不可达,0代表该位置可达。

每⾛过⼀个位置就将地图的对应位置标记,以免重复。

找到通路后打印每⼀步的坐标,最终到达终点位置。

封装了点Dot,以及深度优先遍历⽤到的Block,⼴度优先遍历⽤到的WideBlock。

private int[][] map = { //迷宫地图,1代表墙壁,0代表通路{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}};private int mapX = map.length - 1; //地图xy边界private int mapY = map[0].length - 1;private int startX = 1; //起点private int startY = 1;private int endX = mapX - 1; //终点private int endY = mapY - 1; //内部类,封装⼀个点public class Dot{private int x; //⾏标private int y; //列标public Dot(int x , int y) {this.x = x;this.y = y;}public int getX(){return x;}public int getY(){return y;}}//内部类,封装⾛过的每⼀个点,⾃带⽅向public class Block extends Dot{private int dir; //⽅向,1向上,2向右,3向下,4向左public Block(int x , int y) {super(x , y);dir = 1;}public int getDir(){return dir;}public void changeDir(){dir++;}}/*⼴度优先遍历⽤到的数据结构,它需要⼀个指向⽗节点的索引*/public class WideBlock extends Dot{private WideBlock parent;public WideBlock(int x , int y , WideBlock p){super(x , y);parent = p;}public WideBlock getParent(){return parent;}}⼆、回溯法 思路:从每⼀个位置出发,下⼀步都有四种选择(上右下左),先选择⼀个⽅向,如果该⽅向能够⾛下去,那么就往这个⽅向⾛,当前位置切换为下⼀个位置。

迷宫问题的求解与优化

迷宫问题的求解与优化

[课程设计题二]
迷宫问题的求解与优化
[问题描述]
以回溯方法(试探法)和图的广度优先搜索法(路径最短的最优解)求解迷宫的路径,并以图形界面动画的步进方式显示,如下图为回溯方法得到的一个解。

老鼠有四个试探方向。

搜索的回溯算法可以使用栈结构(也可以应用递归)来求解,求最优解就是按图的广度优先搜索求最短路径,两者分开进行。

算法的每一步搜索动作应与界面的变化相协调。

[基本要求]
迷宫的状态可以有几种构造方法,固定的、随机的和人工手动的;也可以用人工方式对固定或随机的方案进行局部的修改。

搜索的动作快慢应能加以调节。

[测试数据]
可先以大小为20*20的迷宫(四周是围墙)进行测试,固定形态的迷宫应包括最终走通和走不通的各种情况;然后测试随机形态的迷宫,再测试人工布局的迷宫。

最后测试大尺寸的迷宫。

[实现提示]
回溯搜索算法可参阅《数据结构》P50,最短路径的算法可参阅《数据结构及应用算法教程》P162。

界面的动作和搜索的单步操作可分别调试完成,最后再通过彼此发消息的方式合成。

迷宫的每一个小单元、老鼠、入点、出点和记载走通的黄色单元格可考虑使用小位图来实现。

最终的图形界面建议如下,如迷宫较大可考虑使用滚动条。

[问题讨论]
迷宫分四方向问题和八方向问题之分,可在解决四方向问题后,再解八方向问题。

迷宫的求解

迷宫的求解

课程设计的名称:迷宫的求解问题1. 问题描述:迷宫只有两个门,一个叫做入口,另一个叫做出口。

把一只老鼠从一个无顶盖的大盒子的入口处赶进迷宫。

迷宫中设置很多隔壁,对前进方向形成了多处障碍,在迷宫的唯一出口处放置了一块奶酪,吸引老鼠在迷宫中寻找通路以到达出口。

求解迷宫问题,即找出从入口到出口的路径。

2. 基本要求:(1)首先建立一个表示迷宫的数据结构;(2)要有试探方向和栈的设计;(3)不能重复到达某点,不能发生死循环;3. 算法思想:若当前位置可通,则纳入路径,继续前进;若当前位置不可通,则后退,换方向继续探索;若四周均无通路,则将当前位置从路径中删去。

4. 模块划分:(1)int maze[n1][n2]是首先建立一个迷宫的矩阵,0为通路,1为不通。

(2)main()函数将初始化top[],使得所有的开始方向为左。

(3)采用回溯法不断地试探并且及时的纠正错误,使得能够找到正确的路径。

5.数据结构(1)坐标点的结构定义如下:typedef struct node{int x;int y;int c;}linkstack;(2)迷宫的数据结构定义如下:maze[m][n]maze[i][j]=0 通路maze[i][j]=1 不通6. 源程序:#include<stdio.h>#include<stdlib.h>#define n1 10#define n2 10typedef struct node{int x;//存x坐标int y;//存y坐标int c;//存该点可能的下点所在的方向,1表示向右,2向上,3向左,4向右}linkstack;linkstack top[100];//迷宫矩阵int maze[n1][n2]={1,1,1,1,1,1,1,1,1,1,0,0,0,1,0,0,0,1,0,1,1,1,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,0,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,};int i,j,k,m=0;main(){//初始化top[],置所有方向数向左for(i=0;i<n1*n2;i++){top[i].c=1;}printf("the maze is:\n");//打印原始迷宫矩阵for(i=0;i<n1;i++){for(j=0;j<n2;j++)printf(maze[i][j]?"*":"");printf("\n");}i=0;top[i].x=1;top[i].y=0;maze[1][0]=2;//回溯算法do{if(top[i].c<5)//还可以向前试探{if(top[i].x==5&&top[i].y==9)//已经找到一个组合{//打印路径printf("The way %d is:\n",m++);for(j=0;j<=i;j++){printf("(%d,%d)-->",top[j].x,top[j].y);}printf("\n");//打印选出路径的迷宫for(j=0;j<n1;j++){for(k=0;k<n2;k++){if(maze[j][k]==0)printf("");else if(maze[j][k]==2)printf("0");else printf("*");}printf("\n"); }maze[top[i].x][top[i].y]=0;top[i].c=1;i--;top[i].c+=1;continue; }switch(top[i].c)//向前试探{case 1:{if(maze[top[i].x][top[i].y+1]==0){i++;top[i].x=top[i-1].x;top[i].y=top[i-1].y+1;maze[top[i].x][top[i].y]=2;}else{top[i].c+=1;}break; }case 2:{if(maze[top[i].x-1][top[i].y]==0){i++;top[i].x=top[i-1].x-1;top[i].y=top[i-1].y;maze[top[i].x][top[i].y]=2;}else{top[i].c+=1;}break;}case 3:{if(maze[top[i].x][top[i].y-1]==0){i++;top[i].x=top[i-1].x;top[i].y=top[i-1].y-1;maze[top[i].x][top[i].y]=2;}else{top[i].c+=1;}break;}case 4:{if( maze[top[i].x+1][top[i].y]==0){i++;top[i].x=top[i-1].x+1;top[i].y=top[i-1].y;maze[top[i].x][top[i].y]=2;}else{top[i].c+=1;}break;}}}else//回溯{if(i==0)return 0;//已经找完所有解maze[top[i].x][top[i].y]=0;top[i].c=1;i--;top[i].c+=1;}}while(1);}7. 测试情况:截图:结果分析:通过程序运行的结果可以看出,此程序能够实现在有一个入口一个出口的情况下选择路径的功能,并且就此程序而言,有多条路径可以选择。

数据结构课程设计_迷宫求解

数据结构课程设计_迷宫求解

迷宫求解一.问题描述对迷宫问题的求解过程实际就是从入口开始,一步一步地走到出口的过程。

基本要求:输入一个任意大小的迷宫数据,用递归和非递归两种方法求出一条走出迷宫的路径,并将路径输出。

二.设计思路在本程序中用两种方法求解迷宫问题-非递归算法和递归算法。

对于非递归算法采用回溯的思想,即从入口出发,按某一方向向前探索,若能走通,并且未走过,则说明某处可以到达,即能到达新点,否则试探下一方向;若所有的方向均没有通路,或无路可走又返回到入口点。

在求解过程中,为了保证在到达某一点后不能向前继续行走(无路)时,能正确返回前一点以便继续从下一个方向向前试探,则需要用一个栈保存所能到达的没一点的下标与该点前进的方向,然后通过对各个点的进出栈操作来求得迷宫通路。

对于递归算法,在当前位置按照一定的策略寻找下个位置,在下个位置又按照相同的策略寻找下下个位置…;直到当前位置就是出口点,每一步的走法都是这样的。

随着一步一步的移动,求解的规模不断减小;如果起始位置是出口,说明路径找到,算法结束,如果起始位置的四个方向都走不通,说明迷宫没有路径,算法也结束。

另外,为了保证迷宫的每个点都有四个方向可以试探,简化求解过程,将迷宫四周的值全部设为1,因此将m行n列的迷宫扩建为m+2行,n+2列,同时用数组来保存迷宫阵列。

三.数据结构设计在迷宫阵列中每个点都有四个方向可以试探,假设当前点的坐标(x,y),与其相邻的四个点的坐标都可根据该点的相邻方位而得到,为了简化问题,方便求出新点的坐标,将从正东开始沿顺时针进行的这四个方向的坐标增量放在一个结构数组move[4]中,每个元素有两个域组成,其中x为横坐标增量,y为纵坐标增量,定义如下:typedef struct{int x,y;}item;为到达了某点而无路可走时需返回前一点,再从前一点开始向下一个方向继续试探。

因此,还要将从前一点到本点的方向压入栈中。

栈中的元素由行、列、方向组成,定义如下:typedef struct{int x,y,d;}DataType;由于在非递归算法求解迷宫的过程中用到栈,所以需定义栈的类型,本程序中用的是顺序栈,类型定义如下;typedef struct{DataType data[MAXSIZE];int top;}SeqStack, *PSeqStack;四.功能函数设计(1)函数PSeqStack Init_SeqStack()此函数实现对栈的初始化工作。

迷宫问题

迷宫问题

问题求解报告1.题目简述:迷宫问题迷宫问题就是在8行8列的迷宫中寻找一条或多条从进口到出口的路径,并显示迷宫于屏幕同时显示出路径。

试以程序求出由入口至出口的路径。

2.求解方法:递归法首先用二维数组表示迷宫的结构,用2表示迷宫墙壁,使用1来表示行走路径,用0表示进口和出口。

其中迷宫用随机函数产生,即调用随机函数产生二维数组,进而用二维数组表示迷宫的结构。

采用递归法:在任意一个位置都有上、左、下、右四个行进方向,在每前进一格之前就选一个方向前进,无法前进时退回选择下一个可前进方向,然后选择一个行进顺序:先向右,后向下,再向左,最后向上;如此在二维数组中依序测试四个方向。

因此可以用递归调用,设置一个访问函数f(int i, int j):现在我们行进到A(i,j)处,依次判断其是否可以向右,向下,向左,向上前进,如果可以向右就优先向右,递归调用该函数f(i,j+1),如果不可以向右就判断是否可以向下,如果可以就递归调用函数f(i+1,j),直至递归函数的参数为出口的坐标,否则结束此次递归,返回没有可行的路径。

同时f也要用来处理某格是否被访问过,若被访问救将该处的值改为1。

3.结合程序代码的分析:(1).随机产生密迷宫的函数程序代码:void Random(int mg[8][8]){int i,j,k;srand((unsigned int )time(NULL));for(i=1;i<7;i++)for(j=1;j<7;j++){k=rand()%3; //随机生成0、1、2三个数if(k)mg[i][j]=0;elseelsemg[i][j]=2;}}for(j=0;j<8;j++)mg[0][j]=mg[7][j]=2; /*设置迷宫外围"不可走",保证只有一个出口和入口*/for(i=0;i<8;i++)mg[i][0]=mg[i][7]=2; /*设置迷宫外围"不可走",保证只有一个出口和入口*/mg[1][0]=mg[6][7]=mg[1][1]=mg[6][6]=0; //将入口、出口设置为"0"即可通过;因为距入口或出口一步的路是必经之路,置于0;}(2).递归调用程序代码:void visit(int i, int j) { //访问各个格子,按优先顺序:先右,后下,再左,最后向上int m, n;maze[i][j] = 1;if(i == endI && j == endJ) {printf("\n显示路径:\n");for(m = 0; m < 8; m++) {for(n = 0; n < 8; n++)if(maze[m][n] == 2)printf("□");else if(maze[m][n] == 1)printf("◇");elseprintf(" ");printf("\n");}}if(maze[i][j+1] == 0) visit(i, j+1); //递归调用if(maze[i+1][j] == 0) visit(i+1, j);if(maze[i][j-1] == 0) visit(i, j-1);if(maze[i-1][j] == 0) visit(i-1, j);maze[i][j] = 0;}由于迷宫的设计,老鼠走迷宫的入口至出口路径可能不只一条,如何求出所有的路径呢?求所有路径看起来复杂但其实更简单,只要在老鼠走至出口时显示经过的路径,然后退回上一格重新选择下一个位置继续递回就可以了,比求出单一路径还简单,我们的程式只要作一点修改就可以了。

迷宫求解

迷宫求解

数据结构实验报告——迷宫求解1、问题描述以一个m x n的长方矩阵表示迷宫,0和1分别表示迷宫中的通路和障碍。

设计一个程序,对任意设定的迷宫,求出从入口到出口的通路,或者没有通路的结论。

2、需求分析1、以二维数组migong[M][N]表示迷宫,其中migong[0][j]和migong[i][0](0<=j,i<=N)为添加的一圈障碍。

数组中以元素0表示通路,1表示障碍,迷宫的大小理论上可以不限制。

2、迷宫数据由程序提供,用户只需要进行选择迷宫就行。

迷宫的入口和出口由程序提供。

3、若设定的迷宫存在通路,则以长方形矩阵的形式将迷宫及其通路输出到标准终端上,其中“0”表示障碍,“2”表示通过的路径,“3”表示死胡同,没有显示的区域表示没有到达过的地方。

4、本程序只求出一条成功的通路。

但是只要对函数进行小量的修改,就可以求出其他全部的路径。

5、程序执行命令为:(1)、创建迷宫;(2)、求解迷宫;(3)、输出迷宫。

3、概要设计a、设定栈的抽象数据类型定义:ADT zhan{数据对象:D={ai|ai属于yanshu,i=1、2…n,n>0}数据关系:R={<ai-1,ai>|ai-1,ai属于D,i=2,3,…n}基本操作:gouzhan(*s,*migong)操作结果:构造一个空栈push(*s,*e)初始条件:栈已经存在操作结果:将e所指向的数据加入到栈s中pop(*s,*e)初始条件:栈已经存在操作结果:若栈不为空,用e返回栈顶元素,并删除栈顶元素getpop(*s,*e)初始条件:栈已经存在操作结果:若栈不为空,用e返回栈顶元素popover(*s)初始条件:栈已经存在操作结果:输出栈中的所有元素,同时清空栈stackempty(*s)初始条件:栈已经存在操作结果:判断栈是否为空。

若栈为空,返回1,否则返回0destroy(*s)初始条件:栈已经存在操作结果:销毁栈s}ADT zhanb、设定迷宫的抽象数据类型定义ADT yanshu{数据对象:D={ai,j|ai,j属于{‘’、‘0’、‘2’、‘3’},0<=i<=M,0<=j<=N}数据关系:R={ROW,COL}ROW={<ai-1,j,ai,j>|ai-1,j,ai,j属于D,i=1,2,…M,j=0,1,…N}COL={<ai,j-1,ai,j>|ai,j-1,ai,j属于D,i=0,1,…M,j=1,2,…N}基本操作:gouzhaomigong(*migong,m,n)初始条件:二维数组migong[m][n]已经存在,其中第1至第m-1行,每行自第1到第n-1列的元素已经值,并以值0表示障碍,值1表示通路。

数据结构 迷宫求解

数据结构 迷宫求解

数据结构迷宫求解数据结构迷宫求解1- 引言本文档旨在介绍使用数据结构解决迷宫问题的方法。

迷宫求解是一个经典的问题,涉及到遍历、图论等算法知识。

通过本文档的学习,读者将能够了解如何使用数据结构来解决迷宫问题,以及相关的算法和实现。

2- 迷宫问题概述2-1 迷宫定义迷宫是一个有围墙和通道组成的结构,其中只有一个入口和一个出口。

迷宫的通道可以用坐标来表示,如(x, y),其中x和y分别表示迷宫中的行号和列号。

2-2 迷宫求解目标迷宫求解的目标是找到从入口到出口的一条路径。

路径应该遵循以下规则:●只能沿着通道移动,不能穿过墙壁。

●每一步只能向上、下、左、右四个方向移动。

●不允许走重复的路径。

3- 使用栈求解迷宫问题3-1 栈的定义栈是一种先进后出(Last In First Out, LIFO)的数据结构。

栈的主要操作包括入栈(push)和出栈(pop)。

3-2 解题思路使用栈来解决迷宫问题的基本思路如下:●从起点开始,将起点入栈。

●栈顶元素出栈,并将其标记为已访问。

●查找当前位置的相邻可访问的通道。

如果存在未访问的相邻通道,则将其入栈。

●重复以上步骤,直到找到终点位置或者栈为空。

●如果找到终点位置,则栈中的元素即为解决迷宫问题的路径。

4- 迷宫求解算法实现4-1 数据结构选择为了实现迷宫求解,我们可以使用以下数据结构:●二维数组:用于表示迷宫的结构。

●栈:用于保存访问路径。

4-2 伪代码以下是使用栈求解迷宫问题的伪代码示例:```function solveMaze(maze):Initialize an empty stackPush the entrance coordinates (startX, startY) onto the stackwhile the stack is not empty:Pop the top element from the stackSet the current coordinates (currX, currY) to the popped elementMark the current coordinates as visitedif the current coordinates are the exit:return the stack as the solution pathfor each neighboring cell (nextX, nextY) of the current cell:if the neighboring cell is a valid and unvisited path:Push the neighboring cell coordinates onto the stackreturn \。

数据结构课程设计迷宫问题求解

数据结构课程设计迷宫问题求解

数据结构课程设计迷宫问题求解正文:1:问题描述迷宫问题是一个经典的问题,其目标是找出从入口到出口的路径。

我们需要设计一个算法,解决给定迷宫的问题。

2:问题分析首先,我们需要通过数据结构来表示迷宫。

可以使用二维数组来表示迷宫的格子,其中0表示可通行的路径,1表示墙壁或障碍物。

3:迷宫求解算法3.1 深度优先搜索算法深度优先搜索算法是一种递归算法,从入口开始,不断地往下搜索,直到找到出口或者搜索完整个迷宫。

在搜索过程中,需要标记已经访问过的格子,以避免重复搜索。

3.2 广度优先搜索算法广度优先搜索算法使用队列来进行搜索,从入口开始,先将入口加入队列中,然后遍历队列中的所有相邻格子,将未访问过的格子加入队列中。

直到找到出口或者队列为空。

3.3 最短路径算法最短路径算法可以使用Dijkstra算法或者A算法。

Dijkstra算法使用了优先队列,通过计算每个格子到入口的距离,选择最短路径。

A算法在计算格子到入口的距离时,还考虑了格子到出口的距离的估算值。

4:程序实现4.1 数据结构设计我们使用二维数组来表示迷宫的格子,使用一个额外的二维数组来标记已访问的格子。

可以使用一个结构体来表示每个格子的坐标。

4.2 算法实现我们需要实现深度优先搜索算法、广度优先搜索算法以及最短路径算法。

可以使用递归来实现深度优先搜索算法,使用队列来实现广度优先搜索算法,使用优先队列来实现最短路径算法。

4.3 界面设计可以使用命令行界面来输入迷宫的大小和格子的类型,以及展示迷宫的解法和最短路径。

5:测试与结果分析我们需要对设计的算法进行测试,并对结果进行分析。

可以创建一些不同大小和复杂度的迷宫,对算法进行测试,并统计算法的时间复杂度和空间复杂度。

6:附件本文档涉及的附件包括程序源代码和测试数据。

7:法律名词及注释7.1 数据结构:指在计算机中组织和存储数据的方式,包括数组、链表、栈、队列等。

7.2 深度优先搜索算法:一种使用递归的搜索算法,从一个节点开始,优先搜索其相邻节点,直到达到目标节点或无法继续搜索为止。

迷宫问题的求解(广度和深度优先搜索)

迷宫问题的求解(广度和深度优先搜索)

迷宫问题的求解(⼴度和深度优先搜索)迷宫问题主要可以分为两类,⼀个是深度优先搜索和⼴度优先搜索。

⼴度优先搜索常⽤于求最优解(如最短时间,最优路径等),站在⼀个点上,⾸先试⼀试⾃⼰周围的点是否可以⾛,如果是路则加⼊待⾛队列,如果是墙则丢弃。

迷宫问题在⼴度优先搜索的时候需要特别注意的就是要及时抛弃,遇到⾛过的点⽴即丢弃,遇到墙⽴即丢弃,不然时间复杂度就很⾼。

⼀般利⽤队列来辅助。

深度优先搜索则不需最优的特性,⽤于求解有或者没有的问题。

⼀般利⽤堆栈或递归来实现。

下⾯先介绍简单的⼆叉树的⼴度和深度优先遍历1//⼴度优先遍历2void BFS(Tree root)3 {4 queue<Node>Q;5 Q.push(root);6 Node temp;7while( Q.empty()==false){8 template = Q.front();9 Q.pop();10 printf("%d",temp->data);11if( temp->lchild){12 Q.push(temp->lchild);13 }14if( temp->rchild){15 Q.push(temp->rchild);16 }17 }1819 }1//深度优先遍历2void DFS( Tree root)3 {4 stack <Node> S;5 S.push(root);6 Node node;7while( S.empty()){8 node = S.top();9 printf("%d",node->data);10 S.pop();11if( node->rchild){12 S.push(node->rchild);13 }14if( node->lchild){15 S.push( node->lchild);16 }17 }18 }胜利⼤逃亡题⽬描述Ignatius被魔王抓⾛了,有⼀天魔王出差去了,这可是Ignatius逃亡的好机会.魔王住在⼀个城堡⾥,城堡是⼀个A*B*C的⽴⽅体,可以被表⽰成A个B*C的矩阵,刚开始Ignatius被关在(0,0,0)的位置,离开城堡的门在(A-1,B-1,C-1)的位置,现在知道魔王将在T分钟后回到城堡,Ignatius每分钟能从⼀个坐标⾛到相邻的六个坐标中的其中⼀个.现在给你城堡的地图,请你计算出Ignatius能否在魔王回来前离开城堡(只要⾛到出⼝就算离开城堡,如果⾛到出⼝的时候魔王刚好回来也算逃亡成功),如果可以请输出需要多少分钟才能离开,如果不能则输出-1.<center></center>输⼊描述:输⼊数据的第⼀⾏是⼀个正整数K,表明测试数据的数量.每组测试数据的第⼀⾏是四个正整数A,B,C和T(1<=A,B,C<=50,1<=T<=1000),它们分别代表城堡的⼤⼩和魔王回来的时间.然后是A块输⼊数据(先是第0块,然后是第1块,第2块......),每块输⼊数据有特别注意:本题的测试数据⾮常⼤,请使⽤scanf输⼊,我不能保证使⽤cin能不超时.在本OJ上请使⽤Visual C++提交.输出描述:对于每组测试数据,如果Ignatius能够在魔王回来前离开城堡,那么请输出他最少需要多少分钟,否则输出-1.⽰例1输⼊13 34 200 1 1 10 0 1 10 1 1 11 1 1 11 0 0 10 1 1 10 0 0 00 1 1 00 1 1 0输出11这道题⼀开始看题看半天,其实它就是3*3*4=36个点,是⼀个⽴体的图形,下⾯的0,1就是表⽰那个点是路还是墙1 #include<stdio.h>2 #include<queue>34using namespace std;6bool mark[50][50][50]; //标记数组7int maze[50][50][50]; //保存⽴⽅体信息89struct Node10 {11int x,y,z;12int t;13 };14 queue<Node> Q;1516int go[][3]17 {181,0,0,19 -1,0,0,200,1,0,210,-1,0,220,0,1,230,0,-124 };2526int BFS(int a,int b,int c)27 {28int i;29 Node temp;30while( Q.empty()==false)31 {32 Node now = Q.front();33 Q.pop();34for( i=0; i<6; i++)35 {36//依次扩展6个相邻结点37int nx = now.x+go[i][0];38int ny = now.y+go[i][1];39int nz = now.z+go[i][2];40if( nx<0 || nx>=a || ny<0 || ny>=b || nz<0|| nz>=c)41continue; //若再⽴⽅体外则丢弃42if( maze[nx][ny][nz]==1)43continue; //若为墙则丢弃44if( mark[nx][ny][nz]==true)45continue; //若访问过则丢弃4647 temp.x = nx;48 temp.y = ny;49 temp.z = nz;50 temp.t = now.t+1;51 Q.push(temp); //新位置加⼊队列中52 mark[nx][ny][nz] = true; //标记该位置53if( nx==a-1 && ny==b-1 && nz==c-1)54return temp.t; //到达终点55 }56 }57return -1;58 }59int main()60 {61int n;62int i,j,k;63int a,b,c,t;64int ret;65 scanf("%d",&n);66while( n--)67 {6869 scanf("%d%d%d%d",&a,&b,&c,&t);70for( i=0; i<a; i++)71 {72for( j=0; j<b; j++)73 {74for( k=0; k<c; k++)75 {76 scanf("%d",&maze[i][j][k]);77 mark[i][j][k] = false;78 }79 }80 }81while( Q.empty()==false) Q.pop(); //清空队列82 mark[0][0][0] = true; //标记起点83 Node temp;84 temp.t = temp.x = temp.y = temp.z=0;85 Q.push(temp);86 ret = BFS( a,b,c);87if( ret<=t) printf("%d\n",ret); //成功逃出输出时间,⽆法找到终点输出-188else printf("-1\n"); //若时间超过返回-189 }90return0;91 }Tempter of the bone时间限制:1秒空间限制:32768K 热度指数:148题⽬描述The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze began to shake, and the doggie could feel the groundsinking. He realized that the bone was a trap, and he tried desperately to get out of this maze.The maze was a rectangle with sizes N by M. There was a door in the maze. At the beginning, the door was closed and it would open at the T-th second for a short period oftime (less than 1 second). Therefore the doggie had to arrive at the door on exactly the T-th second. In every second, he could move one block to one of the upper, lower, leftand right neighboring blocks. Once he entered a block, the ground of this block would start to sink and disappear in the next second. He could not stay at one block for morethan one second, nor could he move into a visited block. Can the poor doggie survive? Please help him.输⼊描述:The input consists of multiple test cases. The first line of each test case contains three integers N, M, and T (1 < N, M < 7; 0 < T < 50), which denote the sizes of the maze and the time at which the door will open, respectively. The next N lines 'X': a block of wall, which the doggie cannot enter;'S': the start point of the doggie;'D': the Door; or'.': an empty block.The input is terminated with three 0's. This test case is not to be processed.输出描述:For each test case, print in one line "YES" if the doggie can survive, or "NO" otherwise.⽰例1输⼊4 4 5S.X...X...XD....3 4 5S.X...X....D0 0 0输出NOYES题⽬⼤意:有⼀个n*m的迷宫,包括起点s,终点d,墙x和地⾯,0秒时主⼈公从s出发,每秒能⾛到四个与其相邻的位置中的⼀个,且每个位置被⾏⾛之后都不能再次⾛⼊,问是否存在这样⼀条路径使在T秒刚好⾛到d1 #include<stdio.h>2 #include<stdlib.h>34char maze[8][8]; //保存地图信息5int n,m,t;6int flag; //是否找到的标记7int go[][2]=8 {91,0,10 -1,0,110,1,120,-113 };1415void DFS( int x,int y, int time)16 {17int i;18int nx,ny;19for( i=0; i<4; i++)20 {21//枚举四个相邻位置2223int nx = x + go[i][0];24int ny = y + go[i][1];25if( nx<1 || nx>n || ny<1 || ny>m) continue;26if( maze[nx][ny]=='X') continue; //若该位置为墙,跳过27if( maze[nx][ny]=='D') //若该位置为门28 {29if( time+1 == t)30 {31//判断时间32 flag = 1 ;33return;34 }35else continue;36 }3738 maze[nx][ny] = 'X'; //修改该位置为墙39 DFS( nx, ny, time+1); //递归扩展该状态40 maze[nx][ny] = '.';41if( flag==1 ) return; //假如成功,直接返回42 }43 }44int main()45 {46int i,j;47int sx,sy;48while( scanf("%d%d%d",&n,&m,&t)!=EOF)49 {50if( n==0 && m==0 && t==0) break;5152for( i=1; i<=n; i++)53 {54//建构迷宫55 scanf("%s",maze[i]+1);56 }57 flag = 0; //初始化成功标记58for( i=1; i<=n; i++)59 {60for( j=1; j<=m; j++)61 {62if( maze[i][j]=='D')63 {64//寻找D位置的坐标65 sx = i;66 sy = j;67 }68 }69 }70for( i=1; i<=n; i++)71 {72for( j=1; j<=m; j++)73 {74if( maze[i][j]=='S' && (i+j)%2 ==((sx+sy)%2+t%2)%2 )75 {76//找到S点77 maze[i][j] = 'X';78 DFS(i,j,0);7980 }81 }82 }83if( flag ) printf("YES\n");84else printf("NO\n");85 }86return0;87 }这道题⼀开始剪枝不够提⽰超时,后加⼊(i+j)%2 ==((sx+sy)%2+t%2)%2这个判断的意思是每⾛⼀步,只有⼀个坐标分量发⽣增⼀或减⼀的改变,那么两个坐标分量和的奇偶性将发⽣变化。

迷宫问题——精选推荐

迷宫问题——精选推荐

迷宫问题问题:下图给出了⼀个迷宫的平⾯图,其中标记为 1 的为障碍,标记为 0 的为可以通⾏的地⽅。

010000000100001001110000迷宫的⼊⼝为左上⾓,出⼝为右下⾓,在迷宫中,只能从⼀个位置⾛到这个它的上、下、左、右四个⽅向之⼀。

第⼀种⽅案(最短路径):对于上⾯的迷宫,从⼊⼝开始,可以按DRRURRDDDR 的顺序通过迷宫,⼀共 10 步。

第⼆种⽅案(不是最短路径):这⾥我的代码只能⾛到右下⾓,但并不是以最少的步数⾛到的。

(⽤了12步)其中 D、U、L、R 分别表⽰向下、向上、向左、向右⾛。

请你⽤程序实现以上⾛迷宫的步骤思路:递归求解直接上代码:1public class Maze {2private static int[][] maze = {3 {0,1,0,0,0,0},4 {0,0,0,1,0,0},5 {0,0,1,0,0,1},6 {1,1,0,0,0,0},7 };89/**10 * 0 代表还没⾛11 * 1 代表墙12 * 2 代表已经⾛过,⾛的通13 * 3 代表已经⾛过,⾛不通14 * 规定⾛的顺序:先右、然后下、再左、最后上15 * @param i16 * @param j17 * @return18*/19public static boolean mazeReCall(int i, int j) {20if (maze[3][5] == 2) {21return true;22 }2324// 边界索引越界25if (i < 0 || i >= maze.length || j < 0 || j >= maze[i].length ) {26return false;27 }2829// 看这个点有没有⾛过,没有就可以⾛,即maze[i][j] = 030if (maze[i][j] == 0) {31// 初始认为该点不是死路,即设置为2,然后去判断⾃⼰的四个⽅向是否有可通的路32 maze[i][j] = 2;33if (mazeReCall(i, j + 1)) {34// 右35return true;36 } else if (mazeReCall(i + 1, j)) {37// 下38return true;39 } else if (mazeReCall(i, j - 1)) {40// 左41return true;42 } else if (mazeReCall(i - 1, j)) {43// 上44return true;45 } else {46// 上下左右都⾛不通,将该点设置为3,即死路47 maze[i][j] = 3;48return false;49 }50 } else {51// 不为0就直接返回false,表⽰⾛不通,此时可能为1、2、352/*53什么是死路?就是三个⽅向都⾛不通的路,即为思路(注意:不是四个⽅向都⾛不通才为思路)54这⾥2为什么也返回false呢?因为我们知道⼀个死胡同(即死路)是有⼀个进去的⽅向,另外三个⽅向都⾛不通55不然如果2也能⾛的话,那么就会⽆限次的来回⾛这个点,⽆限判断,⽆限返回,就不跟现实相符了。

数据结构课程设计——迷宫求解问题

数据结构课程设计——迷宫求解问题

《数据结构课程设计:迷宫》实验报告任务分配:●程序员:主要任务:负责整体的算法设计以与程序的主要源代码的编写。

●测试员:主要任务:负责在程序员每完成一个阶段对程序进行挑错,测试主程序并对实验结果进行整理分析,最后完成实验报告的第三、四部分即测试结果与分析探讨的内容。

●文档员:主要任务:负责对程序与界面的美观提出改善意见,查找程序的小漏洞,负责撰写实验报告的第一、二部分即实验内容简介与算法描述的内容。

同时完成整个文档的整合,使整篇报告排版、文字风格统一。

一、简介图的遍历就是从指定的某个顶点(称其为初始点)出发,按照一定的搜索方法对图中的所有顶点各做一次访问过程。

根据搜索方法不同,遍历一般分为深度优先搜索遍历和广度优先搜索遍历。

,并将其本实验中用到的是广度优先搜索遍历。

即首先访问初始点vi的所有未被访问过的邻接点,顺序任意,并标记为已访问过,接着访问vi均标记为已访问过,以此类推,直到图中所有和初始点v有路径相通的顶i点都被访问过为止。

鉴于广度优先搜索是将所有路径同时按照顺序遍历,直到遍历出迷宫出口,生成的路径为最短路径。

因此我们采用了广度优先搜索。

无论是深度优先搜索还是广度优先搜索,其本质都是将图的二维顶点结构线性化的过程,并将当前顶点相邻的未被访问的顶点作为下一个顶点。

广度优先搜索采用队列作为数据结构。

本实验的目的是设计一个程序,实现手动或者自动生成一个n×m矩阵的迷宫,寻找一条从入口点到出口点的通路。

具体实验内容如下:选择手动或者自动生成一个n×m的迷宫,将迷宫的左上角作入口,右下角作出口,设“0”为通路,“1”为墙,即无法穿越。

假设一只老鼠从起点出发,目的为右下角终点,可向“上、下、左、右、左上、左下、右上、右下”8个方向行走。

如果迷宫可以走通,则用“■”代表“1”,用“□”代表“0”,用“☆”代表行走迷宫的路径。

输出迷宫原型图、迷宫路线图以与迷宫行走路径。

如果迷宫为死迷宫,则只输出迷宫原型图。

迷宫智力测试题目及答案

迷宫智力测试题目及答案

迷宫智力测试题目及答案一、选择题1. 以下哪个选项是迷宫的入口?A. 起点B. 终点C. 死胡同D. 交叉点答案:A2. 如果在迷宫中遇到一个有四个通道的交叉点,你应该如何选择?A. 随机选择一个通道B. 选择最宽的通道C. 选择最窄的通道D. 观察四周,选择最有可能通往出口的通道答案:D二、填空题3. 迷宫中,______是最常见的障碍物。

答案:墙壁4. 当你在迷宫中迷失方向时,可以采用______技巧来找到出口。

答案:右手法则三、简答题5. 描述一种在迷宫中快速找到出口的方法。

答案:一种快速找到出口的方法是使用“右手法则”,即始终保持右手触碰墙壁,沿着墙壁走,这样最终会找到出口。

四、判断题6. 在迷宫中,如果你发现自己回到了起点,那么你应该立即放弃。

答案:错误7. 迷宫中的每个通道都有可能是通往出口的路。

答案:正确五、计算题8. 如果一个迷宫有100个交叉点,每个交叉点平均有4个通道,那么迷宫中总共有多少条通道?答案:迷宫中总共有400条通道。

六、应用题9. 假设你在一个有10个房间的迷宫中,每个房间有3个门通向其他房间。

如果你从起点出发,不考虑返回,最多可以访问多少个房间?答案:最多可以访问10个房间,因为每个房间只能进入一次。

七、推理题10. 在一个复杂的迷宫中,你发现了一张纸条,上面写着:“向左走三次,然后向右走一次,你会找到宝藏。

”根据这个线索,你应该如何行动?答案:根据线索,你应该先向左走三次,然后向右走一次,按照这个顺序行动,最终找到宝藏。

迷宫求解

迷宫求解

迷宫求解一.需求分析:(1)以二维数组Maze [m+1][n+1]表示迷宫,其中:Maze[0][0]和Maze[m+1][0]及Maze[0][n+1]和Maze[m+1][n+1]为添加的障碍,不予显示。

数组中以元素值为0表示通路,1表示障碍。

(2)根据用户的需要,动态开辟迷宫的行数、列数。

(3)迷宫的出入口由用户自己确定。

(4)由随机函数产生的迷宫若存在通路,则给出提示“以找到一条路径”,并给出此路径(第i步:点(p,q)格式),并给出演示算法:用箭头表示行走的路径。

(5)测试数据:输入迷宫的行数为10和列数为15,输出为:(见下图)二.概要设计设计栈的抽象结构类型定义int M,N;//迷宫的大小typedef int MazeType[100][100]; //用较大的数100,最外凿初始化成墙,实际含M,N个格子typedef int Status;typedef int ElemType; //迷宫数组中的元素类型#define STACK_INIT_SIZE 100#define STACKINCREMENT 10typedef struct{int x;int y;}PosType;//坐标的位置typedef struct{int ord;PosType seat;int di;}SElemType;//栈中元素类型typedef struct{SElemType *base;SElemType *top;int stacksize;}Stack;//栈类型具体函数如下:Status InitStack(Stack &S)//构造空栈SStatus Push(Stack &S, SElemType e)//插入e为栈顶元素Status Pop(Stack &S,SElemType &e)//栈顶元素出栈并用e带回其值Status GetTop(Stack S,SElemType &e)//取出栈顶元素Status StackEmpty(Stack S)//判空Status StackTraverse(Stack S,Status (*visit)(SElemType))//访问栈中元素Status PrintSElem(SElemType e)Status MakeMaze(MazeType &maze,int M,int N)//生成迷宫,"1或2"表示通PATH1或PATH2,"0"表示不通W ALLvoid PrintMaze(MazeType maze)//输出迷宫三.详细设计1.坐标位置类型typedef struct{int x;int y;}PosType;//坐标的位置2.栈类型typedef struct{SElemType *base;SElemType *top;int stacksize;}Stack;//栈类型3.把元素压入栈里Status Push(Stack &S, SElemType e)//插入e为栈顶元素{if(S.top-S.base>=S.stacksize){S.base=(SElemType *) realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));if(!S.base) exit(OVERFLOW);S.top=(S.base+S.stacksize);S.stacksize+=STACK_INIT_SIZE;}*S.top++=e; //top指向待插入位置return OK;}4访问栈中元素Status StackTraverse(Stack S,Status (*visit)(SElemType))//访问栈中元素{SElemType *p=S.base;if(S.base==S.top)printf("空栈\n");elsewhile(p<S.top){(*visit)(*p);++p;}return OK;}5.迷宫的自动生成Status MakeMaze(MazeType &maze,int M,int N)//生成迷宫,"1或2"表示通PATH1或PATH2,"0"表示不通W ALL{PosType m;srand(time(NULL));for(m.y=0;m.y<=N-1;m.y++){maze[0][m.y]=BOUNDARY;maze[M-1][m.y]=BOUNDARY;}for(m.x=1;m.x<=N-2;m.x++){maze[m.x][0]=BOUNDARY;maze[m.x][N-1]=BOUNDARY;}for(m.x=1;m.x<=M-2;m.x++)for(m.y=1;m.y<=N-2;m.y++)maze[m.x][m.y]=rand()%4;//产生随机数0,1,2,3,墙与非墙1:3 return OK;}6.探索路径可通过if(maze[curpos.x][curpos.y]==PA TH1 || maze[curpos.x][curpos.y]==PA TH2 ||maze[curpos.x][curpos.y]==PATH3)//当前位置可通{e.ord=curstep;e.seat=curpos;e.di=1;//当前位置加入路径Push(S,e);if(curpos.x==end.x && curpos.y==end.y)//当前位置就是终点{maze[curpos.x][curpos.y]=DESTINATION;return OK;}else{maze[curpos.x][curpos.y]=RIGHT;//从其向右走curpos=Nextpos(curpos,1);//下一位置是右边curstep++;}}7.探索下一步操作PosType Nextpos(PosType position,ElemType direction){PosType curdir;//当前位置curdir=position;switch (direction){case 1:curdir.y++;break;case 2:curdir.x++;break;case 3:curdir.y--;break;case 4:curdir.x--;break;}return curdir;}四.测试结果自行设置的迷宫行数为10,列数为15,得到迷宫如下:此迷宫可用,输入非零数10有:设置入口为(1,1),出口为(10,15)得到图形如下:五.结果分析与总结本程序设计符合题目要求,实现了寻找到一条通路,可以从刚开始探索到目标点(10,15),运用了栈的相关知识对迷宫进行求解。

迷宫问题非递归求解

迷宫问题非递归求解

迷宫问题非递归求解(总9页)本页仅作为文档页封面,使用时可以删除This document is for reference only-rar21year.March题目:迷宫问题非递归求解一、需求分析迷宫问题非递归求解,要求实现以下任务:(1)、可以输入一个任意大小的迷宫数据;(2)、用非递归的方法求出一条走出迷宫的路径;(3)、将路径输出;二、总体设计对于迷宫问题的非递归求解,我采用二维指针即指向指针的指针来保存迷宫,采用顺序栈来探寻迷宫路径,最后将路径输出。

寻找一条走出迷宫的路径时,当下一方向可以走时(为0时),就入栈,若下一方向不可走时就退栈,再次试探另一方向是否可以走,可走再入栈,到达新的一点时依此反复。

最后就可以得到迷宫的路径。

将路径输出时则采用退栈方式,依次输出路径。

三、详细设计四、实现部分//maze.h头文件#include<iostream> #include<stack>#include<stdio.h>#include<string> using namespace std;typedef struct{int x,y,d;}Datetype;typedef struct{int x,y;int pre;}SqType;typedef stack<Datetype> stack_int;class maze{public:void print(SqType sq[],int);void again(int **maze,int m,int n);void find(int **maze,int a,int b,int m,int n);void create();private:int front,rear;};class Stack{public:void Push();int Pop();Stack();~Stack();private:int top;int data[1000];};//maze.cpp成员函数#include "maze.h"#include"iostream"void maze::print(SqType sq[],int){int i;i=rear;do{cout<<"("<<sq[i].x<<","<<sq[i].y<<")<—";i=sq[i].pre;}while(i!=-1);}void maze::again(int **maze,int m,int n){for(int i=1;i<=m;i++){for(int j=1;j<=n;j++){if(maze[i][j]==-1)maze[i][j]=0;}}}void maze::find(int **maze,int a,int b,int m,int n){Datetype move[4]={{0,1},{1,0},{0,-1},{-1,0}};stack_int st;Datetype temp;int x,y,d,i,j;if(maze[a][b]==1){cout<<"进口输入有误。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

迷宫求解问题摘要:用矩阵表示迷宫,将矩阵表示的迷宫转换成无向图,用邻接表存储。

对无向图从入口结点开始广度优先搜索,用一个一维数组存储各个结点的前驱结点的编号,通过出口结点Vn找到其前驱结点Vn-1,再通过Vn-1找到Vn-2,依次类推直到找到出口结点。

关键字:矩阵迷宫求解一、需求分析1.程序题目:迷宫求解问题。

迷宫是一个如下所示的m行n列的0-1矩阵,0表示无障碍,1表示有障碍。

设入口为(1,1),出口为(m,n),每次移动只能从一个无障碍的单元移到周围8个方向的任意一个无障碍的单元,编写程序给出一条通过迷宫的路径或者报告一个“无法通过”的信息。

入口->(0,0,0,1,0,0,0,1,0,0,0,1,0,0,1)(0,1,0,0,0,1,0,1,0,0,0,1,1,1,1)(0,1,1,1,1,1,0,1,0,0,1,1,1,0,1)(1,1,0,0,0,1,1,0,1,1,0,0,1,0,1)(1,0,0,1,0,1,1,1,1,0,1,0,1,0,1)(1,0,1,0,0,1,0,1,0,1,0,1,0,1,0)(1,0,1,1,1,1,1,0,0,1,1,1,1,0,0)(1,1,1,0,1,1,1,1,0,1,0,1,0,1,0)(1,0,1,0,1,0,1,1,1,0,1,0,0,0,1)(0,1,0,1,0,1,0,0,0,1,1,0,0,1,0)->出口2.程序说明及任务:迷宫问题要求寻找一条从入口到出口的路径。

路径是由一组位置构成的,每个位置上都没有障碍,且每个位置(第一个除外)都是前一个位置的东、南、西或北的邻居,如图C。

计算机走迷宫的方法是,采取一步一步试探的方法。

每一步都从东开始,按顺时针对8个方向进行试探,若某方向上maze(x,y)=0,表示可以通行,则走一步;若maze(x,y)=1,表示不可以通行,须换方向再试,直到8个方向都试过;若maze (x,y)均为1,说明此步已无路可走,需退回一步,在上一步的下一个方向重新开始探测。

为此,需设置一个栈,用于记录所走过的位置和方向(i,j,dir)。

当退回一步时,从栈中退出一个元素,以便在上一个位置的下一个方向上探测,如又找到一个行进方向,则把当前位置和方向重新进栈,并走到新的位置。

若探测到位置(m,n),则已经到达迷宫的出口,可以停止探测,输出存在栈中的路径;如果在某一位置的8个方向上堵塞,则退回一步,继续探测;如果已退到迷宫的入口(栈中无元素),则表示此迷宫无路径可走。

二、概要设计主要思想:1. 用矩阵表示的迷宫;2. 将矩阵表示的迷宫转换成无向图,用邻接表存储;3. 对无向图从入口结点开始广度优先搜索;4. 用一个一维数组存储各个结点的前驱结点的编号;5. 通过出口结点Vn找到其前驱结点Vn-1,再通过Vn-1找到Vn-2;6. 依次类推直到找到出口结点。

基本设计算法:1. 设置数组maze[MAX][MAX]来模拟迷宫,2. maze [i][j]=0表示该方格所在的位置可通行, A[i][j]=1则表明该位置不能通行;3. 定义无向图G,迷宫的规格(行、列)存放在G.rownum、G.colnum中,其结点数同迷宫(数组maze [MAX][MAX])的方格个数。

4. 每一个结点的邻接结点为其相邻(从点在数组maze [][]中所处的位置的角度)的八个点中值为0的点,按结点的顺序依次找出每一个点的邻接点,此即完成迷宫图的数组表示转化为无向图表示,G用邻接表存储;5. 采用图的广度优先遍历的方法,从入口结点开始遍历,直到碰到出口结点为止。

并设置record数组来记录结点i在广度优先遍历过程中的前驱结点的编号record[i];6. 这样(record[i],i)表示存在从结点record[i]到i的边,这样就可以从出口顶点在图中的编号回溯出口顶点,如此,一条从入口到出口的最短路径就找到了。

在定义record数组是将所有初始值设为-1,只是为了判断是否存在从入口到出口的路径,因为如果出口结点i的record[i]值为-1则表明遍历过程没有找到出口,也就是说此迷宫无解.7. 反之record[i]!= -1,则此迷宫一定是有解的,因为只有遍历过程中找到了出口I,才会改变record[i]的值,而这个改变后的值是不可能为-1的;8. 输出从入口到出口的路径,用回溯法,只需将图中结点的编号换算成数组maze的坐标即可。

三、详细设计1. 基本过程的算法:设定a[0][0]为入口位置;do{若当前位置可通,则{将当前位置插入栈顶;若该位置是出口位置,则结束;否则切换当前位置的东邻方块为新的当前位置;}否则,若栈不空且栈顶位置尚有其他方向未经探索,则设定新的当前位置为沿顺时针方向旋转找到的栈顶位置的下一相邻块;若栈不空但栈顶位置的四周均不可通,则{删栈顶位置;若栈不空,则重新测试新的栈顶位置,直到找到一个可通的相邻块或出栈至栈空;}}while(栈不空);#include <malloc.h>2. 函数的调用关系图迷宫存储从A[0][0]开始,包括记录路径的数组record[]也是从0下标开始纪录的,为了使输入和输出的坐标符合习惯,只在输入输出时作了一些改变。

迷宫主要部分转换图示矩阵转化成图的邻接表存储:[i](G.vexs[i].data,G.vexs[i].first)→(adjno,next)[1] (0,first)→(11,NULL)[2] (1,NULL)[3] (1,NULL)……[11](0,first)→(21,next)→(1,NULL)……[59](0,first)→(60,next)→(49,NULL)[60](0,first)→(59,NULL)以入口结点作广度优先遍历的起始结点,知道找到出口结点结束遍历,并用record[i]记录遍历的结点i的前驱结点record[i],然后用回溯法输出路径(路径换算成坐标形式)即可。

3.抽象数据类型定义描述① ADT T isData当前位置的行坐标、当前位置的列坐标、走到下一位置的方向end ADT T② ADT Linknode isData数据域、指针域OperationLinknode //构造函数用于构造结点end ADT LinkNode③ ADT Stack isData栈顶指针OperationStack //构造函数输入:无初始化栈:置空栈~stack //析构函数 Push输入:要进栈的项e前置条件:无动作:把e压入栈顶输出:无后置条件:栈顶增加了一个新结点,栈顶指针指向新结点 Pop输入:无前置条件:栈非空动作:弹出栈顶元素输出:返回栈顶元素的值后置条件:删除栈顶元素GetPop动作:返回栈顶元素的值Clear动作:清空栈empty动作: 检查栈顶指示是否等于NULL输出:栈空时返回1,否则返回0end ADT Stack四、调试分析1)程序将用到的函数及参数:1. 迷宫输入: adjlist input (int maze [][MAX]);2. 迷宫图的图结构(邻接表存储)化: adjlist convert (int maze [][MAX],adjlistG);3. 对图的广度优先遍历: void travgraph(adjlist G,int record[],int entry,int exit);4. 迷宫的解的输出: void output (adjlist G,int record[],int entry,int exit)。

2)算法分析和改进在程序的设计中,总的调试比较顺利。

在找出一些小问题顺利编译成功以后,在测试结果的时候发现程序运行的结果错误。

经过仔细的检查,发现程序中8个if语句中的算法出现错误。

导致运行时搜索的方向发生错误。

在if语句中的”i-1<G.colnum&&j+1<G.colnum”转换为”i-1>=0&&j+1<G.colnum”后,错误解除。

经过测试结果,结果正确。

虽然程序能够编译成功,但是还有2个警告项存在.winTC提示警告:success.c 126 :不可移动的指针(地址常数)转换在travgraph 函数中。

success.c 132 :不可移动的指针(地址常数)转换在travgraph 函数中。

经过改进,问题成功解决。

警告消失。

对于不能显示汉语的TC,最后将中文转换为英文,唯一不足的是(*,*)在显示的时候是乱码。

未能几时改进。

3)体会:要能很好的掌握编程,仅仅通过几个简单的程序的编写是无法达成的,更需要大量积累和深入才有可能。

就从这个迷宫的问题来说,在迷宫图向图结构的转化时,对图可用广度优先搜索的算法来解决两点间路径问题。

在程序的编写中也不能一味得向已有的程序进行模仿,而要自己去摸索,去寻求最好的解决方式,只有带着问题去反复进行实践,才能更熟练的掌握和运用,当然,对现有的程序也要多去接触,因为有些程序是我们无法在短时间内想出来的。

最重要的一点就是要持之以恒,要经常性的复习原来所接触的程序,这样才能保证我们有足够的经验去面对程序问题。

五、测试结果:1.运行出现“Please input the length of the maze”字样,“rownum”表示输入”行数”“colnum”表示输入”列数”。

2.然后会出现“Input the 1 row”这时输入数组的第一行,后面的依次类推。

3.数组输入完毕后,会出现” Inputting the maze entrance sits the mark(*,*)”即输入起点坐标。

然后会出现”Inputting the maze exports to sit the mark (*,*)”要求输入出口坐标。

4.点击回车运行所求的路径即会显示出来。

所示输入迷宫大小:行数(<=15):10 [↙]列数(<=15):15[↙]0表示可通行,1表示不能通过。

输入第1行:[1] 00010001000100 1输入第2行:[2] 01000101000111 1 输入第3行:[3] 01111101001110 1 输入第4行:[4] 11000110110010 1 输入第5行:[5] 10010111101010 1 输入第6行:[6] 101001010101010 输入第7行:[7] 101111100111100 输入第8行:[8] 111011********* 输入第9行:[9] 10101011101000 1 输入第10行:[10] 010101000110010 输入入口坐标(*,*):1,1输入出口坐标(*,*):10,15附录1.存储结构:邻接表存储存储2.基本过程的算法:(1). 栈初始化;(2). 将入口点坐标及到达该点的方向(设为-1)入栈;(3). while(栈不空时){ 栈顶元素元素(x,y,d)出栈;求出下一个要试探的方向d++;while (还有剩余试探方向时){ if(d方向可走)则{ (x,y,d)入栈;求新点坐标(i,j);将新点(i,j)切换为当前点(x,y);if ((x,y)= = (n,n))结束;else d=0;}else d++; }}3.源程序:#include <stdio.h> #define MAX 15#define NULL 0 typedef struct listnodestruct listnode *next;}listnode;typedef struct{int data;listnode *first;}headnode;typedef struct {headnode vexs[MAX*MAX]; int vexnum;int rownum;int colnum;}adjlist;/*输入迷宫,0为可通行,1为不可通行,用二维矩阵表示*/adjlist input (int maze[][MAX],adjlist G){int i,j;int rownum,colnum;printf("Please input the length of the maze:\n");printf("rownum=");scanf("%d",&G.rownum);printf("colnum=");scanf("%d",&G.colnum);for(i=0;i<G.rownum;i++){printf("Input the %d row:[%d] ",i+1,i+1);for(j=0;j<G.colnum;j++)scanf("%d",&maze[i][j]);}return(G);}/*二维数组向无向图的转化*/adjlist change (int maze[][MAX],adjlist G){int i,j;listnode *p;G.vexnum=G.rownum*G.colnum;for(i=0;i<G.vexnum;i++) /*图中结点的初始化*/ {G.vexs[i].data=maze[i/G.colnum][i%G.colnum];G.vexs[i].first=NULL;}for(i=0;i<G.rownum;i++) /*将无向边用指针表示出来*/ for(j=0;j<G.colnum;j++){if(i-1>=0&&maze[i-1][j]==0){p=(listnode *)malloc(sizeof(listnode));p->adjno=(i-1)*G.colnum+j;p->next=G.vexs[i*G.colnum+j].first;G.vexs[i*G.colnum+j].first=p;}if(i+1<G.rownum&&maze[i+1][j]==0){p=(listnode *)malloc(sizeof(listnode));p->adjno=(i+1)*G.colnum+j;p->next=G.vexs[i*G.colnum+j].first;G.vexs[i*G.colnum+j].first=p;}if(j-1>=0&&maze[i][j-1]==0){p=(listnode *)malloc(sizeof(listnode)); p->adjno=i*G.colnum+j-1;p->next=G.vexs[i*G.colnum+j].first; G.vexs[i*G.colnum+j].first=p;}if(j+1<G.colnum&&maze[i][j+1]==0){p=(listnode *)malloc(sizeof(listnode)); p->adjno=i*G.colnum+j+1;p->next=G.vexs[i*G.colnum+j].first; G.vexs[i*G.colnum+j].first=p;}if(i-1>=0&&j-1>=0&&maze[i-1][j-1]==0) {p=(listnode *)malloc(sizeof(listnode)); p->adjno=(i-1)*G.colnum+j-1;p->next=G.vexs[i*G.colnum+j].first;G.vexs[i*G.colnum+j].first=p;}if(i-1>=0&&j+1<G.colnum&&maze[i-1][j+1]==0) {p=(listnode *)malloc(sizeof(listnode));p->adjno=(i-1)*G.colnum+j+1;p->next=G.vexs[i*G.colnum+j].first;G.vexs[i*G.colnum+j].first=p;}if(i+1<G.colnum&&j-1>=0&&maze[i+1][j-1]==0) {p=(listnode *)malloc(sizeof(listnode));p->adjno=(i+1)*G.colnum+j-1;p->next=G.vexs[i*G.colnum+j].first;G.vexs[i*G.colnum+j].first=p;}if(i+1<G.colnum&&j+1<G.colnum&&maze[i+1][j+1]==0){p=(listnode *)malloc(sizeof(listnode));p->adjno=(i+1)*G.colnum+j+1;p->next=G.vexs[i*G.colnum+j].first;G.vexs[i*G.colnum+j].first=p;}}return(G);}/* 用int travgraph()函数广度优先遍历无向图*/int travgraph(adjlist G,int record[],int entry,int exit){listnode *p;int queue[MAX*MAX],visited[MAX*MAX]; /*用visited[]数组标记图的结点是否遍历过*/int i;int front=0,rear=1;for(i=0;i<G.rownum*G.colnum;i++){record[i]=-1;/*置record[i]为-1,以便检查从入口到出口结点V[n]有无通路*/visited[i]=0;}visited[entry]=1;queue[rear]=entry;while(front!=rear) /*记录遍历路径,(record[i],i)表示存在从结点record[i]到i的边*/{p=G.vexs[queue[front+1]].first;while(p!=NULL){if(visited[p->adjno]==0){visited[p->adjno]=1;record[p->adjno]=queue[front+1];queue[++rear]=p->adjno;if(p->adjno==exit)goto end;}p=p->next;}front=front+1;}end:;}/*用回溯法找到从出口到入口的路径,并输出*/ void output (int record[],int entry,int exit) {int i=0,t;if(entry==exit&&G.vexs[exit].data==0)printf("It's already at export\n");elseif(record[exit]!=-1){t=exit;{printf("The most short path is as follows:\n");while(t!=entry){printf("[%d,%d]<-",t/G.colnum+1,t%G.colnum+1); t=record[t];if(++i%5==0)printf("\n");}printf("[%d,%d]",t/G.colnum+1,t%G.colnum+1);}}elseprintf("Have no path from the entrance to the exit\n");}void main(){int entry_row,entry_col,exit_row,exit_col,entry,exit;int maze[MAX][MAX];int record[MAX*MAX];G=input(maze,G);G=change(maze,G);printf("Inputting the maze entrance sits the mark(*,*):"); scanf("%d,%d",&entry_row,&entry_col);printf("Inputting the maze exports to sit the mark(*,*):"); scanf("%d,%d",&exit_row,&exit_col);entry=--entry_row*G.colnum+--entry_col;exit=--exit_row*G.colnum+--exit_col;travgraph(G,record,entry,exit);output(record,entry,exit);getch();}4.测试数据和结果输入:行数(<=15):10 [↙]列数(<=15):15[↙]0表示可通行,1表示不能通过。

相关文档
最新文档