5*5迷宫路径问题

问题描述:

东东有一张地图,想通过地图找到终点。地图显示,0表示可以走,1表示不可以走,左上角是入口,右下角是终点,这两个位置保证为0。既然已经知道了地图,那么东东找到终点就不难了,请你编一个程序,写出东东找到终点的最短路线。

input: 输入是一个5 × 5的二维数组,仅由0、1两数字组成,表示法阵地图。
output: 输出若干行,表示从左上角到右下角的最短路径依次经过的坐标,格式如样例所示。数据保证有唯一解。

解题思路:

首先看到这题目,已知是5*5的地图,那么就可以用一个静态数组来存储该地图。并且在行走过程中要存储点的坐标,所以定义一个结构体来表示这个坐标,其中有横坐标x和纵坐标y两个成员。

并且对于这个问题来说,由于要找到最短路径,则我们可以想到用广度优先搜索bfs,因为bfs是一层一层的遍历,所以得到的路径肯定是最短的。在bfs过程中,我们要考虑一个点有没有走过,则我们用一个vis二维数组来进行标记,一开始初始化为0,如果走到该点则进行标记,将vis数组的值赋为1。在该迷宫中。每一次bfs要考虑四个方向,上下左右依次去访问,这四个方向可以表示在坐标的变换上,则我们定义两个数组,来表示x和y坐标的变化。由于要储存坐标,则用一个结构体类型的数组from来存储该坐标的上一个位置,这样我们我们有一个位置就能找到其上一个位置,以便于最后输出。

在每一次bfs中,我们都要特判终点,如果x和y坐标都为5,则退出。如果不是,在进行坐标变换时,都必须保证坐标在迷宫内,并且没有障碍物和标记,这样才能将其压入队列。在将其压入队列时,记录该点from数组的值,并将vis数组的值标记为1。

在输出时,定义一个vector数组,从终点开始,依据from数组的值,不断寻找其上一个元素,并将其插入vector数组末尾,知道起点位置,然后将vector数组进行倒叙输出。

解题总结:

在这个题目当中,想到用bfs是该题目的突破口,并且怎样在bfs过程中保留路径是一个难题,通过一个数组,数组的下标就是该坐标,其值为其上一个可到达的点,这样就可以不断调用该数组,进行结果输出。

代码:

#include<iostream>
#include<queue>
using namespace std; 
struct local{  //坐标结构体
	int x;
	int y;
};
int a[6][6];   //迷宫数组
int vis[6][6];  //该点是否可到达
int move_x[]={1,-1,0,0};
int move_y[]={0,0,1,-1};
local from[6][6];  //存储上一个位置
int main()
{
	for(int i=1;i<=5;i++)
	{
		for(int j=1;j<=5;j++)
			vis[i][j]=0;
	}
	//输入迷宫
	for(int i=1;i<=5;i++)
	{
		for(int j=1;j<=5;j++)
			cin>>a[i][j];
	}
	queue<local> store;
	vis[1][1]=1;  //将起点标记
	local ll;
	from[1][1]=ll; 
	ll.x=1;
	ll.y=1;
	store.push(ll);
	vis[1][1]=1;
	while(!store.empty())
	{//bfs
		local temp=store.front();
		store.pop();
		//特判终点
		if((temp.x==5)&&(temp.y==5))
			break;
		//访问周围四个点
		for(int i=0;i<4;i++)
		{
			int newx=temp.x+move_x[i];
			int newy=temp.y+move_y[i];
			//判断该点是否合法
			if(newx>=1&&newx<=5&&newy>=1&&newy<=5&&vis[newx][newy]==0&&a[newx][newy]==0)
			{
				local tt;
				tt.x=newx;
				tt.y=newy;
				store.push(tt);
				from[newx][newy]=temp;
				vis[newx][newy]=1;
			}
		}
	}
	vector<local> p;//路线保留在数组中
	int n_x=5,n_y=5;
	while((n_x!=1)||(n_y!=1))
	{
		local qq;
		qq.x=n_x;
		qq.y=n_y;
		p.push_back(qq);
		int te;
		te=from[n_x][n_y].x;
		n_y=from[n_x][n_y].y;
		n_x=te;
	}
	p.push_back(ll);
	for(int i=p.size()-1;i>=0;i--)//倒序输出
	{
		cout<<"("<<p[i].x-1<<", "<<p[i].y-1<<")\n"; 
	}
 } 

问题描述: 以一个m*n的长方阵表示迷宫,0和1分别表示迷宫的通路和障碍。设计一个程序,对任意设定的迷宫,求出从入口(0,0)到出口(m-1,n-1)的通路和通路总数,或得出没有通路的结论。例如下图, 0(入口) 1 0 1 0 0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0(出口) 从入口到出口有6条不同的通路。 而下图: 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 1 1 0 1 0 1 1 1 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 0 0 0 1 0 1 1 1 0 0 0 0 0 0 从入口到出口则没有通路。 算法设计: 给定一个m*n的长方阵表示迷宫设计算法输出入口到出口的通路和通路总数,或得出没有通路的结论。 算法提示: 和皇后问题与分书问题类似。可以用二维数组存储迷宫数据,对于迷宫任一位置,均可约定有东、南、西、北四个方向可通。从当前位置a(用(x,y)表示一个位置,假定它是以向右的x轴和向下的y轴组成的平面上的一个点)出发依次尝试四个方向是否有路,若某个方向的位置b可通,则按照同样的方法继续从b出发寻找。若到达出口,则找到一条通路。 数据输入: 由文件input.txt 提供输入数据。第一行是m和n的值,空格分隔,其后共m行。每行有n个数字,数和数之间用空格分隔。 结果输出: 将计算出的所有从入口到出口的通路输出到文件output.txt 。若没有通路,则将0写入文件
要解决迷宫最短路径问题,可以使用广度优先搜索算法(BFS)来实现BFS算法广泛应用于图形和树的搜索问题,其从起点开始扩展每个节点,并在扩展的所有节点上重复此过程,直到找到目标节点。 以下是一个使用C++语言实现5*5规格迷宫最短路径问题的示例代码: ```c++ #include <iostream> #include <queue> using namespace std; const int MAXN = 5; // 迷宫规格 int maze[MAXN][MAXN] = { // 迷宫地图 {0, 1, 0, 0, 0}, {0, 1, 0, 1, 0}, {0, 0, 0, 0, 0}, {0, 1, 1, 1, 0}, {0, 0, 0, 1, 0} }; int d[MAXN][MAXN]; // 到达每个点的最短距离 int dx[4] = {-1, 0, 1, 0}; // 方向数组 int dy[4] = {0, 1, 0, -1}; struct Node { int x, y; }; int bfs() { queue<Node> q; Node s = {0, 0}; // 起始节点 q.push(s); memset(d, -1, sizeof(d)); d[0][0] = 0; while (!q.empty()) { Node cur = q.front(); q.pop(); if (cur.x == MAXN-1 && cur.y == MAXN-1) break; // 到达终点 for (int i = 0; i < 4; ++i) { int nx = cur.x + dx[i]; int ny = cur.y + dy[i]; if (nx >= 0 && nx < MAXN && ny >= 0 && ny < MAXN && maze[nx][ny] == 0 && d[nx][ny] == -1) { // 可行的下一步 Node next = {nx, ny}; q.push(next); d[nx][ny] = d[cur.x][cur.y] + 1; } } } return d[MAXN-1][MAXN-1]; } int main() { cout << bfs() << endl; return 0; } ``` 在上面的代码,我们使用了一个结构体`Node`来表示节点的坐标。首先将起始节点入队并将到达每个点的最短距离初始化为-1。在每次循环,我们从队列取出一个节点,并在其周围四个方向扩展节点。如果下一步是可行的,则将其入队,并将到达该节点的最短距离更新为当前节点的最短距离+1。 最后,我们返回到达终点的最短距离。对于上述的迷宫,该代码将输出9,即到达右下角的最短距离为9。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值