@。啊哈算法,java篇之层层递进_广度优先搜索

本文深入探讨了使用Java实现广度优先搜索(BFS)的技巧,作为啊哈算法系列的一部分。通过层层递进的示例,帮助读者理解BFS在解决搜索问题中的应用。
摘要由CSDN通过智能技术生成
package 第四章;

import java.awt.print.Book;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Scanner;

public class 层层递进_广度优先搜索 {
	static int[][] next = {
			{0,1},
			{1,0},
			{0,-1},
			{-1,0}
	};
	static class Node{
		int x;
		int y;
		int step;
		public int getX() {
			return x;
		}
		public void setX(int x) {
			this.x = x;
		}
		public int getY() {
			return y;
		}
		public void setY(int y) {
			this.y = y;
		}
		public int getStep() {
			return step;
		}
		public void setStep(int step) {
			this.step = step;
		}
//		public Node(int x,int y,int step) {
//			this.x = x;
//			this.y = y;
//			this.step = step;
//		}
	}
	static int[][] a ;//存储地图
	static int[][] book; //标记
	public static void main(String[] args) {
		Queue<Node> que = new LinkedList<Node>();//存x轴
		int head ,tail;
		Scanner input = new Scanner(System.in);
		int n = input.nextInt();//n行
		int m = input.nextInt();//m列
		book = new int[n+1][m+1];
		a = new int[n+1][m+1];
		for (int i = 1; i <=n ; i++) {
			for (int j = 1; j <=m; j++) {
				a[i][j] = input.nextInt();
			}
		}
		int startx = input.nextInt();//
		int starty = input.nextInt();//入口
		
		int endp = input.nextInt();
		int endq = input.nextInt();//小哈位置
		Node node = new Node();
		node.setX(startx);
		node.setY(starty);
		node.setStep(0);
		//队列初始化
		head = 1;
		tail = 1;
		//往队列插入迷宫入口坐标
		que.offer(node);
		
//		tail++;//存入之后,头指针可以往下一个    (其实我在想,根本没必要记录,因为que的方法有这一特性) 事实证明不用!
		book[startx][starty] = 1;
		int flag = 0;//用来记录是否到达目标点,0表示暂时还没有到大,1表示到达了。
		//当队列不是空的时候循环
		/*
		 * 在啊哈算法中,判断条件是head<tail
		 * 然而我们队列方法中的poll()方法取出并删除队头的元素,当队列为空,返回null;
		 * 会自动删除队头元素,
		 * 所以我们只需要判断条件为各个队列是否为空就好。
		 */
//		while (!quex.isEmpty()&&!quey.isEmpty()&&!quef.isEmpty()&&!ques.isEmpty()) {
		while (!que.isEmpty()) {
			//枚举四个方向
			for (int i = 0; i < 4; i++) {
				//计算下一个坐标
				// peek()方法直接取出队头的元素,并不删除.
				int next_x = que.peek().getX() + next[i][0];
				int next_y = que.peek().getY() + next[i][1];
				//判断是否越界
				if (next_x<1||next_x>n||next_y<1||next_y>m) {
					continue;
				}
				//判断是否是障碍物或者已经在路径中
				if (a[next_x][next_y]==0 && book[next_x][next_y]==0) {
					//要记录这个点是否已经走过,
					//要注意广搜的每个点只入队一次,所以和深搜一同,不需要将Book数组还原!!
					book[next_x][next_y] = 1;
					//插入新的点到队列中
					//(个人注释:我认为要先插入再删除,因为这样保证了队列一直不为空)
					Node node2 = new Node();
					node2.setX(next_x);
					node2.setY(next_y);
					node2.setStep(que.peek().getStep()+1);
					que.offer(node2);
					//下面这语句证明,一定要先插入数据在队列后再让队头出队,因为这语句利用了队头的数据
					/*
					 * 那么,问题来了,那该到哪里才将头的数据删除呢?
					 * 接下来考虑的是,这是在一个for循环里面,在这个坐标的四个方向都需要进去一下
					 * 这就意味着,队列是一直在不断扩展的,当扩展完了四个方向,这就意味着这个坐标
					 * 就已经没用处了!没用不就要将它删除了嘛!所以应该是for之外删除!
					 */
//					ques.offer(ques.peek()+1);
//					ques.remove();
//					tail++;(这个同上Head)
				}
				
				//如果到了目标点了,停止扩展,任务结束,退出循环
				if (next_x == endp && next_y == endq) {
					//注意下面两句话的位置不能写颠倒了
					flag = 1;
					break;
				}
			}
			if (flag == 1) break;
			head++;//注意这地方千万不要忘记,当一个点跨站结束之后,head++才能对后面的
			//点再进行扩展
			/*
			 * 其实就是这里,啊哈算法中的head++就是删除,但是我认为他这样的删除就只是不去看它,实际上还是在内存里
			 * 所以我们要删除,用:remove()方法直接删除队头的元素:
			 */
			que.remove();
		}
		
		
		//打印你队列中末尾最后一个点的步数
		//注意tail是指想队列队列(即最后一个位)的下一个位置,所以这需要-1
		/*
		 * 啊哈算法中,有位置可以get到队列的东西,但是que好像没有,都是取队头的东西
		 * 我所以我用了下面很笨拙的方法:
		 * 假设队列有10 长度,那我就删除队头9次不就剩下最后一个嘛?
		 */
		/*
		 *
5 4 
0 0 1 0
0 0 0 0
0 0 1 0
0 1 0 0
0 0 0 1
1 1 4 3
		 */
		//这个是因为不能立即取出队尾,所以通过这个remove队头,当队列的长度为一,就是队尾啦!
		while (que.size()!=1) {
			que.remove();
		}
		System.out.println(que.peek().getStep());
	}
	
	
}

请多多指教!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值