宽度优先搜索BFS算法

news/2024/7/24 4:50:54 标签: bfs, 算法, 宽度优先搜索, acm算法

宽度优先搜索BFS算法


什么是宽度优先搜索

宽度优先搜索(BFS,Breadth_First Search)总是优先搜索距离初始状态近的状态,也就是说,他是按照开始状态->只需一次转移就可以到达的所有状态->只需两次转移就可以到达的所有状态->。。。就这样顺序进行搜索,对于同一个状态,宽度优先搜索只经过一次,因此复杂度为O(状态数*转移的方式)

如何实现宽度优先搜索

深度优先由于是递归,隐式地利用了栈进行计算,而宽度优先搜索则利用了队列。搜索时首先将初始状态加到队列里,此后从队列的最前端不断地取出状态,把从该状态可以转移到的状态中尚未访问过的部分加到队列里,如此往复,知道队列被取空或找到了问题的解。

算法实例:

题干:给定一个大小为N*M的迷宫。迷宫里面由过道和墙壁组成,每一步可以向邻接的上下左右四格过道移动,求从起点到终点所需的最小步数。


限制条件:N,M<=100(S是起点,#是墙壁,.是过道,G是终点)

输入:

N=5

M=5

.S#..
.....
#....
#...#
...G.

输出:6

至少需要走6步,每一步的情况如下
x y
0 1
1 1
1 2
1 3
2 3
3 3
4 3

完整代码如下:

package com.renyou.算法;

import java.awt.Point;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Random;
import java.util.Scanner;

public class 迷宫最短路径的宽度优先BFS算法迷宫自动寻路 {
	private final int INF = 100000000;// 一个不可能的常量来初始化最短距离数组
	private int n, m;// 地图的宽高,即是数组的二维长度
	private char[][] maze;// 二维地图数组 (.表示可以走) ( #表示墙壁)( s表示起点 )(g表示终点)
	private int[][] d;// 到各个位置最短距离的数组
	private int sx, sy;// 起点坐标
	private int gx, gy;// 终点坐标
	private int[] dx = { 1, 0, -1, 0 };// x4个方向的移动向量
	private int[] dy = { 0, 1, 0, -1 };// y4个方向的移动向量
	private List<Point> list = new ArrayList<Point>();// 保存最短路径的坐标

	public static void main(String[] args) {
		new 迷宫最短路径的宽度优先BFS算法迷宫自动寻路().solve();
	}

	private void solve() {
		/************ 控制台输入数据并new数组 ********************/
		Scanner scanner = new Scanner(System.in);
		n = scanner.nextInt();
		m = scanner.nextInt();
		// {{'#','S','.','.','.'},{'#','#','#','#','.'},{'.','.','.','.','.'},{'.','#','#','#','#'},{'.','.','.','G','#'}};
		maze = new char[n][m];
		d = new int[n][m];

		// new Thread() {
		// public void run() {
		// while (true){
		/************* char数组赋值 ********************/

		Random random = new Random();
		int num;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				num = random.nextInt(100);
				if (num % 5 == 0) {
					maze[i][j] = '#';// 墙壁
				} else {
					maze[i][j] = '.';// 路
				}
			}
		}

		/************* 起点终点赋值 ********************/
		sx = 0;
		sy = 1;
		gx = n - 1;
		gy = m - 2;
		maze[sx][sy] = 'S';// 起点
		maze[gx][gy] = 'G';// 终点
		/************ 自动生成的field数组元素输出 *********************/
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				System.out.print(maze[i][j]);
			}
			System.out.println();
		}

		Queue<Point> queue = new LinkedList<Point>();
		// 初始化距离INF
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				d[i][j] = INF;
			}
		}
		// 添加起点到队列并使起点距离为0
		Point point = new Point(sx, sy);// 起点
		queue.offer(point);
		d[sx][sy] = 0;

		while (queue.size() > 0) {
			point = queue.poll();// 拿到队尾元素并删除
			// 如果是终点则结束
			if (point.getX() == gx && point.getY() == gy)
				break;
			// 遍历四个向量
			for (int i = 0; i < 4; i++) {
				int nx = (int) (point.getX() + dx[i]);
				int ny = (int) (point.getY() + dy[i]);
				// 如果点在地图里并且不是墙壁并且从未走过则添加到队列里并且距离加1
				if (0 <= nx && nx < n && 0 <= ny && ny < m && maze[nx][ny] != '#' && d[nx][ny] == INF) {
					queue.offer(new Point(nx, ny));
					d[nx][ny] = d[(int) point.getX()][(int) point.getY()] + 1;
				}
			}
		}
		if (d[gx][gy] == INF) {
			System.out.println("从S到G的路不通");
		}
		// System.out.println("从S到G至少要走" + d[gx][gy] + "步");

//		for (int i = 0; i < n; i++) {
//			for (int j = 0; j < m; j++) {
//				if (d[i][j] ==d[gx][gy]-1&&((Math.abs(i-gx)==1&&j==gy)||(Math.abs(j-gy)==1&&i==gx))){
//					System.out.println(""+i+j);
//				}
//			}
//		}
		/***************遍历d数组不断的找出每个点然后添加到容器********************/
		list.add(new Point(gx, gy));//添加终点
		int number = d[gx][gy];
		boolean flag;
		int f = -1;
		while (number > 0) {
			number--;
			f++;
			flag = true;
			for (int i = 0; i < n; i++) {
				for (int j = 0; j < m; j++) {
					if (d[i][j] == number && ((Math.abs(i - list.get(f).getX()) == 1 && j == list.get(f).getY())
							|| (Math.abs(j - list.get(f).getY()) == 1 && i == list.get(f).getX()))) {
						if (flag) {
							list.add(new Point(i, j));
						}
						flag = false;
					}
				}
			}
		}
		System.out.println("至少需要走" + (list.size() - 1) + "步,每一步的情况如下");
		System.out.println("x y");
		for (int i = list.size() - 1; i >= 0; i--) {
			System.out.println("" + (int) list.get(i).getX() + " " + (int) list.get(i).getY());
		}
		list.clear();
		// try {
		// sleep(1000);
		// } catch (InterruptedException e) {
		// e.printStackTrace();
		// }
		// }
		// }
		// }.start();

	}

}






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

相关文章

vue学习---mockjs

什么是mockjs&#xff1f; Mockjs是一款模拟数据生成器&#xff0c;它可以帮助前段工程师独立于后端进行开发&#xff0c;帮助编写单元测试。Mockjs能做什么&#xff1f; 提供了游侠模拟功能&#xff1a; 1、模拟数据模板生成模拟数据&#xff1b; 2、模拟ajax请求&#xff0c;…

基于bfs搜索算法的迷宫最短路径游戏

基于bfs搜索算法的迷宫最短路径游戏 废话不多说&#xff1a;因为在我的上一篇博客里已经提到了bfs算法.花了一天的时间写的一个小游戏&#xff0c;虽然界面不怎么样&#xff0c;但是算法确实很难写。因为不知道怎么上传文件&#xff08;不然我就整个项目上传了&#xff09;直接…

ubuntu更改源的方法(下载软件加快)

ubuntu更改源的方法 1.备份原来的源&#xff08;以后可能有用&#xff09; sudo cp /etc/apt/sources.list /etc/apt/sources_init.list2.更换源 sudo gedit /etc/apt/sources.list使用gedit打开文档&#xff0c;将下边的阿里源复制进去&#xff0c;然后点击保存关闭。 deb…

Android Mvp架构设计与性能优化

Android Mvp架构设计与性能优化 什么是mvp架构设计&#xff1f; MVP是模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;、主持人&#xff08;Presenter&#xff09;的缩写&#xff0c;分别代表项目中3个不同的模块。 模型&#xff08;Model&#xff09;&…

vmware中让页面全屏的方法

首先点击虚拟机——>安装vmware tools&#xff1b;安装完成后&#xff0c;会在ubuntu中看到这样一个压缩文件&#xff1b; 将该压缩文件复制到你认为可以安装的地方&#xff0c;然后点击右键——>提取到此处&#xff1b;这里也可以cd到这个文件夹&#xff0c;然后用tar命…

android网络访问框架OkHttp的进一步封装

android网络访问框架OkHttp的进一步封装 概述&#xff1a; android网络框架之OKhttp[1]一个处理网络请求的开源项目,是安卓端最火热的轻量级框架,由移动支付Square公司贡献(该公司还贡献了Picasso)[2]用于替代HttpUrlConnection和Apache HttpClient(android API23 6.0里已移除H…

android三级缓存访问网络图片

android三级缓存访问网络图片 什么是三级缓存&#xff1f; 第一级&#xff1a;内存缓存(优先从内存中加载图片&#xff0c;速度最快&#xff0c;不浪费流量) 第二级&#xff1a;本地缓存&#xff08;其次从本地加载图片&#xff0c;速度快&#xff0c;不浪费流量&#xff09; 第…

ubuntu中安装python3.6的方法

首先下载软件安装包&#xff0c;网址为&#xff1a; http://www.python.org/ftp/python/3.6.4/Python-3.6.4.tgz然后进行解压&#xff1a; tar -xvzf Python-3.6.4.tgz进行安装&#xff1b; cd Python-3.6.4./configure --with-ssl进行编译 sudo makesudo make install创建软…