BFS广度优先遍历经典例题迷宫总结

迷宫问题

算法提高 学霸的迷宫

资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
  学霸抢走了大家的作业,班长为了帮同学们找回作业,决定去找学霸决斗。但学霸为了不要别人打扰,住在一个城堡里,城堡外面是一个二维的格子迷宫,要进城堡必须得先通过迷宫。因为班长还有妹子要陪,磨刀不误砍柴功,他为了节约时间,从线人那里搞到了迷宫的地图,准备提前计算最短的路线。可是他现在正向妹子解释这件事情,于是就委托你帮他找一条最短的路线。
输入格式
  第一行两个整数n, m,为迷宫的长宽。
  接下来n行,每行m个数,数之间没有间隔,为0或1中的一个。0表示这个格子可以通过,1表示不可以。假设你现在已经在迷宫坐标(1,1)的地方,即左上角,迷宫的出口在(n,m)。每次移动时只能向上下左右4个方向移动到另外一个可以通过的格子里,每次移动算一步。数据保证(1,1),(n,m)可以通过。
输出格式
  第一行一个数为需要的最少步数K。
  第二行K个字符,每个字符∈{U,D,L,R},分别表示上下左右。如果有多条长度相同的最短路径,选择在此表示方法下字典序最小的一个。
样例输入
Input Sample 1:
3 3
001
100
110

Input Sample 2:
3 3
000
000
000
样例输出
Output Sample 1:
4
RDRD

Output Sample 2:
4
DDRR
数据规模和约定
  有20%的数据满足:1<=n,m<=10
  有50%的数据满足:1<=n,m<=50
  有100%的数据满足:1<=n,m<=500。

关于BFS自己的理解

1.首先能够根据问题,抽象画出一个图,或者一个数,表示各节点之间的关系
例如:迷宫题从(1,1)开始往下走,有上下左右四种情况。然后从上走有上下左右,从下走有上下左右四个路,脑补成一个树。
2.脑海中有了树,使用广度优先遍历一层层的往下找,找到出口即可
3.做题时,按照题目中给出的条件作图,在遍历符合条件的
总结一句话就是,按照题中约束条件限制的情况下作图,广度优先搜索这个图,然后找结果
思路:
这道题应该能判断出使用BFS不断搜索就能找到最终出口。
按照上面的想法,现在题中给出的条件是1不能走,0可以走。所以在入队管理时,除去上下左右为1的路。其次不能走出房间,最后就是走一个结点,将节点标记已访问。
AC代码

#include
using namespace std;
//图中每个结点具有的特性,x表示行,y表示列,Step表示起点到这个点的路径数,s保存路径
struct node{
	int x,y,step;
	string s; 
};
int n,m;//n*m的迷宫
int vis[501][501];//访问过得要标记
char mp[501][501];//输入结果即作图完成
int dir[4][2] = {{1,0},{0,-1},{0,1},{-1,0}};//上下左右四个方向(1,0)表示行加1,列不变,所以表示向下走
char dic[4] = {'D','L','R','U'};//每次选择路径修改
void bfs(){	
    queue<node> q;
	node a,p,next;
	a.x=0;a.y=0;a.step=0;a.s="";vis[0][0]=1;
	q.push(a);//首先把起点放进去,当成根节点,图已建立完成,开始BFS
	while(!q.empty()){
		p=q.front();
		if(p.x==n-1&&p.y==m-1){
			cout<<p.step<<endl<<p.s<<endl;
			break;
		}//判断是否搜到出口
		q.pop();//出队
		//如上面所述,按照作的图来遍历
		for(int i=0;i<4;i++){
			int xx=p.x+dir[i][0];
			int yy=p.y+dir[i][1];//xx,yy表示即将要走的结点  行数,列数,符合条件就走,并入队,修改属性值
			if(xx>=0&&xx<n&&yy>=0&&yy<m&&!vis[xx][yy]&&mp[xx][yy]!='1'){
				next.x=xx;
				next.y=yy;
				next.step=p.step+1;
				next.s=p.s+dic[i];
				vis[xx][yy]=1;
				q.push(next); 
			}
		}
	} 
}
int main()
{
	cin>>n>>m;
	for(int i=0;i<n;i++){
		scanf("%s",mp[i]);
	}
	bfs();
	return 0;
}

例题
http://acm.hdu.edu.cn/showproblem.php?pid=1548
题意:
就是电梯,每个楼层只能上和下,一个固定的数目,给定一个制定的起始层,目的层,求到达目的层最少按几次上下。
例如,5层电梯,起始层1层,目的层5层
1-5层只能上下 3 3 1 2 5层
输入
5 1 5
3 3 1 2 5
0
输出
3
思路:
总结一句话就是,按照题中约束条件限制的情况下作图,广度优先搜索这个图,然后找结果
还是一样,每到一层,只有两种选择,上或下制定层数,所有图的情况就是一个二叉树了,根据约束条件,遍历中如果上超了,下超了,都不可取
AC代码

#include
using namespace std;
int mp[500];//与迷宫一样,储存图或者说储存约束的条件
struct node{
	int x,step;
};//每个结点包含现在的层数以及到此节点走了多少步
int vis[500]={0}; 
int n,s,d;//n层,s开始d结束
int bfs(int n)
{
	queue<node> q;
	node p,start,next;
	start.x=s;start.step=0;vis[s]=1;
	q.push(start);
	while(!q.empty()){
		p=q.front();
		q.pop();
		//cout<
		if(p.x==d){
			return p.step;
			break;
		}//如果已经访问到目的结点,结束。否的话就是有两种情况,分别判断是否入队
		int up=mp[p.x]+p.x;//上的情况
		int down=p.x-mp[p.x];//下的情况
		if(!vis[up]&&up<=n){
			next.x=up;
			next.step=p.step+1;
			vis[up]=1;
			q.push(next);
		}
		if(!vis[down]&&down>=1){
			next.x=down;
			next.step=p.step+1;
			vis[down]=1;
			q.push(next);
		}
	}
	return -1;//没找到目的层,返回-1
} 
int main(){
	while(scanf("%d",&n)!=EOF&&n){
		cin>>s>>d;
		memset(vis,0,sizeof(vis));//太坑了,之前没注意这个一直答案错误 
		for(int i=1;i<=n;i++){
			cin>>mp[i];
		}
		printf("%d\n",bfs(n));
	}   
}

最后再说一句,作图并非一定是给定一个固定的,现成的图。有可能是需要根据题中所给条件抽象构造出一个图,然后一样进行广搜得出答案

你可能感兴趣的:(算法总结)