速戳!小白看 超详细bfs入门/迷宫问题POJ3984

(前面十几行是废话)

zj昨天讲的(什么???)
如果n是13
       (2/n, n-5 ,n-2)为例子
第0层  6        8      11
第1层 3 1 4    4 3 6  5 6 9
第2层
....反正就是类似这样的,
如果下面又遇到了新的5啊这样的,
直接就continue了,因为它肯定不是最优的....




bfs
因为广度优先搜索,只会离初始点的步数一步步增多。
如果之后发现遇到了已走过的点,那肯定是从之前已走过的点那边走最短
而不是从之后发现的点走最短啊
POJ 3984典型的迷宫问题


典型的迷宫问题的话,我差不多明白了
row row row your boat
https://cn.vjudge.net/problem/POJ-3984
有这么几个点




(.....所以zj昨天两个多小时都在讲什么???????)
1.因为是二位的,所以搞了个东西去记录x 和y的坐标
然后,他们是一一对应的,就是x和y的变化
point[4][2]={}
0  1  0 -1
-1 0  1  0
(写的时候写的是,0, -1 1 0 ...这样


2.进行搜索,那个rear,是类似
http://blog.csdn.net/raphealguo/article/details/7523411
里面写的队列,也就是染颜色...
用rear也是吧,如果你是需要等待被搜索的那个,就把你push进去那个队列,把队列一点点往外赶出去


判定条件可以是达到了最后那个条件就满足了
也可以是队列里面没元素了,就是所有的都访问过了


3.代码参考
http://blog.csdn.net/huanghanqian/article/details/51506732
这篇真写的不错


4.如果越界/被vist记录过,访问过,都需要continue掉
然后,如果它最先达到了,它一定是最短的
可以用反证法来说明,如果后面又遇到到达的,所花的步骤肯定比第一个到达的步骤要多
所以肯定是最短的


5.那么复杂度呢,(V+E)
(不太懂)起码要有n,因为你最后到达了n


6.结构体里面的prev是记录了路径,上一个是啥
好了,现在我自己试着写一下这个POJ,稍后会公布抽出的核心代码(?)


这个版本的代码只是用front和rear模拟了一下队列..
//只有,把他们四个全都,遍历完成的时候,才算是出队


print(queue[rear - 1]);//为啥是rear-1?
大概.... 我感觉...因为是都遍历完成了,而且每一个节点,都只访问一次
每个节点都只访问一次,所以每个节点里面记录着的肯定都是最短的所以不怕吧


https://www.cnblogs.com/yueshuqiao/archive/2011/08/22/2149902.html
这个写的更清楚一点
第一个网址是帮助理解的吧,上2行这个网址写起来更通俗易懂一点


****思维过程*****

emmmm......输出问题卡了我一个小时,

前面.....我不想写了.....


#include<iostream>
using namespace std;
int a[5][5];
int point[4][2] = { { -1,0 },{ 1,0 },{ 0,-1 },{ 0,1 } };
//x -1  0 1  0
//y  0 -1 0  1
//x和y,都有这么的几种选择
//int vis[5][5] = { -1 };
struct node {
	int x;
	int y;
	int pre;
} b[50];
//**作为一个结构体,它要有什么?
//这个是一堆数组吧.. 然后d[i].x  d[i.pre].x
//int front = 0;
int rear = 1;

void print(int i) {
	//cout << "(" << d[i.pre].x << "," << d[i.pre].y <<")"<< endl;
	//要保证循环递归自己巴拉巴拉输出完了的话还是用递归来写
	if (b[i].pre!=-1)
	{
		print(b[i].pre);//一直到等于-1,回到上一次的递归的下一行...
		cout << "(" << b[i].x << "," << b[i].y <<")"<< endl;

	}
	
	//i其实无关紧要,重要的是里面的x和y才是你想要的数值
		/*//另一种写法
	void print(node now) {
		if (now.prev != -1)
		{
			print(now.prev);
			cout<<...
		}//然后下面是传进来的node..一样吧应该
		*/
	}



void bfs(int x,int y) {
	int front = 0;
	b[front].x = 0;
	b[front].y = 0;
	b[front].pre = -1;

	while (front < rear)//队列里面,加入了的并且等待筛选的灰色地带还有的话,就
	{
		//***先初始化
		
		int newx, newy;
		
		//四个方向都走一遍吧
		for (int i = 0; i <= 3; i++)
		{
			newx = b[front].x + point[i][0];
			newy = b[front].x + point[i][1];

			
			if (newx < 0 || newy < 0 ||newx>=5||newy>=5 ||a[newx][newy] == 1)
				continue;
			//else
			a[newx][newy] = 1;
			b[rear].x = newx;
			b[rear].y = newy;
			b[rear].pre = front;
			rear++;//入队...front还是当前作为那个啥,,,那个啥的啊
			//rear当序号吧就...这个序号得更新过
			//意会..哪个大哪个小其实都可以
			//因为只是保存/只是提取你搜索的过程就可以了
			if (newx == 1 && newy == 1)
				print(front);
			//***醒目*****
			//然而这里为什么又是front呢...因为front和rear就像是那篇很长的博文里面的点
			//比如从v2出发可以到达v3 v4 v7 
			//v2相当于front v3 4 7相当于是rear
			//输出的时候(4,4)我们特判了,所以输出前驱 就可以啦.
		}front++;
		//四个方向都走完了的时候front也失去了意义,所以相当于出去了..
	}
}
int main()
{
	for(int i=0;i<5;i++)
		for (int j = 0; j < 5; j++)
		{
			cin >> a[i][j];
		}

	
	cout << "(0,0)" << endl;
	bfs(0, 0);
	cout << "(4,4)" << endl;
	return 0;
}

(好吧,我承认这代码是错的.为什么错等下我会在评论区给.....orz)

按顺序来的,后面的front也就相当于前面的rear
void print(Node now){  
    if(now.pre==-1)  
        cout<<"("<<now.x<<", "<<now.y<<")"<<endl;  
    else{  
        print(queue[now.pre]);  
        cout<<"("<<now.x<<", "<<now.y<<")"<<endl;  
    }  
}  (趴)
8.print也可以这么写


9.忽然发现这个题有个特殊性...就是数组a这里,其实它完全已经帮助你优化好了.....
vist为1 或者a输入的是1  都是走不到
初始化都是直接输入a当做初始化.....




我真的觉得很多身份堆到一起的时候脑子不够用....
fine,不管了,做好自己就好
关键是要对得起自己
其他的一切夸张点
全都是小事
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
根据提供的引用内容,可以得知这是一道关于迷宫问题的题目,需要使用Java语言进行编写。具体来说,这道题目需要实现一个迷宫的搜索算法,找到从起点到终点的最短路径。可以使用广度优先搜索或者深度优先搜索算法来解决这个问题。 下面是一个使用广度优先搜索算法的Java代码示例: ```java import java.util.*; public class Main { static int[][] maze = new int[5][5]; // 迷宫地图 static int[][] dir = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; // 方向数组 static boolean[][] vis = new boolean[5][5]; // 标记数组 static int[][] pre = new int[5][5]; // 记录路径 public static void main(String[] args) { Scanner sc = new Scanner(System.in); for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { maze[i][j] = sc.nextInt(); } } bfs(0, 0); Stack<Integer> stack = new Stack<>(); int x = 4, y = 4; while (x != 0 || y != 0) { stack.push(x * 5 + y); int t = pre[x][y]; x = t / 5; y = t % 5; } stack.push(0); while (!stack.empty()) { System.out.print(stack.pop() + " "); } } static void bfs(int x, int y) { Queue<Integer> qx = new LinkedList<>(); Queue<Integer> qy = new LinkedList<>(); qx.offer(x); qy.offer(y); vis[x][y] = true; while (!qx.isEmpty()) { int tx = qx.poll(); int ty = qy.poll(); if (tx == 4 && ty == 4) { return; } for (int i = 0; i < 4; i++) { int nx = tx + dir[i][0]; int ny = ty + dir[i][1]; if (nx >= 0 && nx < 5 && ny >= 0 && ny < 5 && maze[nx][ny] == 0 && !vis[nx][ny]) { vis[nx][ny] = true; pre[nx][ny] = tx * 5 + ty; qx.offer(nx); qy.offer(ny); } } } } } ``` 该代码使用了广度优先搜索算法,首先读入迷宫地图,然后从起点开始进行搜索,直到找到终点为止。在搜索的过程中,使用标记数组记录已经访问过的位置,使用路径数组记录路径。最后,使用栈来输出路径。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值