迷宫问题-分支限界-广度优先搜索

news/2024/6/29 12:16:23 标签: 宽度优先, 算法, c++

走迷宫 分支限界 广度优先搜索

问题描述

在这里插入图片描述

 输入一m×n的矩阵,0表示可以经过的路径,1表示障碍物不可经过。并输入起点坐标s_x,s_y,终点坐标f_x,f_y,试判断能否由起点到达终点,并计算最短路径。

算法思想

 对于寻找路径,很容易想到深搜或者广搜两种方式完成,对于这两种方法都可以完成此目标,因为我们想要用分支限界,因此在这里我们选择广搜。对于计算最短路径,我们可以结合分支限界的思想,采取一定的剪枝策略,减去一定不是问题的解或者不是最优解的分支,以降低算法的时空复杂度从而提升效率。

实现过程

1.创建一个队列Q,初始时将起始位置入队;
2.进入循环,只要队列不为空,就出队队首元素,判断队首元素是否为目标终点,如果是则更新beststep即当前最优路径的长度,否则以队首元素作为扩展结点进行扩展;
3.具体扩展思路:
 在此之前我们还需要一个标记数组以判断标记已经走过的路。然后进行扩展,就是将扩展结点的四个儿子进行判断是否入队,即当前队首元素的上下左右四个方位一一进行判断,如果已经走过或者为障碍物,则不可行,如果可行并且到儿子位置的路径小于当前已经找到的最优路径还要近的话,说明此位置有可能成为我们要寻找的最最优路径上的点,于是入队该位置结点;
4.对于剪枝函数,可根据如下进行设计。当前步数小于最优解步数且该位置合法时,才进入子树进行寻找;

Code

#include"stdio.h"
#include"iostream"
using namespace std;

#define Maxn 9999

typedef struct pos
{
	int x;
	int y;
	int step;
}P;

int M[Maxn][Maxn]; // 迷宫数组
int visit[Maxn][Maxn]; // 标记已经走过的地方 用来剪枝
int m,n; // 行 列
int s_x,s_y,f_x,f_y;// 起点 终点
int beststep = Maxn; // 最优路径步数 初始无穷

int direction[4][2]={{0,-1},{1,0},{0,1},{-1,0}};// 左 下 右 上
// 判断位置是否合法
bool isValid(int x,int y)
{
	if(x<0||y<0||x>=m||y>=n)
		return false;
	else if(M[x][y]==1||visit[x][y]==1)
		return false;
	return true;
}
// 广搜遍历 队列实现 分支限界
bool bfs(int s_x,int s_y,int f_x,int f_y)
{
	P Q[Maxn];// 队列
	int front=0,rear=0;
	P now,next;
	now.x = s_x;
	now.y = s_y;
	now.step = 0;
	Q[rear++] = now;
	while(front!=rear)
	{
		now = Q[front++];
		if(now.x==f_x&&now.y==f_y)
		{
			beststep = now.step;
		}
		for(int i=0;i<4;i++)
		{
			next.x = now.x+direction[i][0];
			next.y = now.y+direction[i][1];
			next.step = now.step+1;
			if(isValid(next.x,next.y)&&next.step<beststep)
			{
				visit[next.x][next.y]=1;
				Q[rear++] = next;
			}
		}
	}
	if(beststep == Maxn)
		return false;
	else
		return true;
}

void main()
{
	int i,j;
	cin>>m>>n;
	for(i=0;i<m;i++)
	{
		for(j=0;j<n;j++)
			cin>>M[i][j];
	}
	cout<<endl;
	for(i=0;i<m;i++)
	{
		for(j=0;j<n;j++)
		{
			cout<<M[i][j]<<" ";
		}
		cout<<endl;
	}
	cout<<"start"<<endl;
	cin>>s_x>>s_y;
	cout<<"final"<<endl;
	cin>>f_x>>f_y;
	bool res = bfs(s_x,s_y,f_x,f_y);
	if(res)
	{
		cout<<"Arrived!"<<endl;
		cout<<"min step is:"<<beststep<<endl;
	}
	else
		cout<<"Can't touch!"<<endl;
}

http://www.niftyadmin.cn/n/782538.html

相关文章

java mongodb spring_MongoDB整合Spring实例详细讲解(含代码)

写这篇文章也做了下思考&#xff0c;首先是本人技术欠佳。但就是喜欢研究一些东西。因为在此之前有很多的朋友已经写过类似的&#xff0c;很多我也看过&#xff0c;但是讲解的不够深入。对有些朋友提出的问题不能给出答案。在这里&#xff0c;我根据我目前的能力对其进行整理。…

学习推荐《从Excel到Python数据分析进阶指南》高清中文版PDF

Excel是数据分析中最常用的工具&#xff0c;本书通过Python与Excel的功能对比介绍如何使用Python通过函数式编程完成Excel中的数据处理及分析工作。在Python中pandas库用于数据处理&#xff0c;我们从1787页的pandas官网文档中总结出最常用的36个函数&#xff0c;通过这些函数介…

java byte转bytebuffer_Java 大小端转换(基于ByteBuffer)

图00 Big-Endian(左)and little-endian(右)大小端的基础知识&#xff1a;小端 ( little-endian)&#xff1a;低位字节在前&#xff0c;高位字节在后。大端(Big-Endian)&#xff0c;则反之。具体而言&#xff0c;就是为了说清楚&#xff0c;CPU架构中1字(word)的存储顺序。计算机…

数据结构——堆排序 C语言

堆排序 堆排序&#xff1a;堆排序是一个时间复杂度为O(nlogn)空间复杂度为O(1)的十分优秀且非常稳定的排序算法&#xff0c;不论是在最好还是最坏情况下&#xff0c;其时间复杂度都稳定在O(nlogn),同时一般也可以用来快速求出一组数据中最大或最小的前几个数。 算法过程 堆排序…

深搜

深搜 搜索与回溯是计算机解题中常用的算法&#xff0c;很多问题无法根据某种确定的计算法则来求解&#xff0c;可以利用搜索与回溯的技术求解。回溯是搜索算法中的一种控制策略。它的基本思想是&#xff1a;为了求得问题的解&#xff0c;先选择某一种可能情况向前探索&#xff…

java xml 解析 _Java解析XML

《java架构宝典》文集说明本文集记载的所有内容均是java的学习笔记&#xff0c;主要重点记录概念&#xff0c;可能不会为每个概念列举完整的代码例子&#xff0c;更多代码例子请移步《java架构宝典》文集若有错漏之处&#xff0c;欢迎各位指正XML简介 XML&#xff0c;可扩展标记…

nodejs动态路由

主要功能&#xff1a;根据输入路由的不同&#xff0c;加载访问不同的HTML页面 在这里我不得不说webstorm真的是一个很棒的开发工具&#xff0c;我学习nodejs也是用的它。 文件目录&#xff1a; first_server.js: 首先我们通过url获取当前路径&#xff0c;变量path来存储。 path…

Docker最全教程之使用Node.js搭建团队技术文档站(二十三)

前言 各种编程语言均有其优势和生态&#xff0c;有兴趣的朋友完全可以涉猎多门语言。在平常的工作之中&#xff0c;也可以尝试选择相对适合的编程语言来完成相关的工作。 在团队技术文档站搭建这块&#xff0c;笔者尝试了许多框架&#xff0c;最终还是选择了Hexo…