bfs----------------------------------广度优先搜索

   概念:

    广度优先搜索(Breadth-First-Seracj)BFS,BFS是一种分层的查找过程,每向前走一步可访问一批顶点,不像深度优先搜索,它不是一个递归的算法,为了实现逐层访问,需要用到一个辅助的队列。

   我的理解:

    就像一棵树,从起点向下找,找遍每一层的所有节点,然后找下级结点,直到找到你想要的

广搜多应用于找,迷宫的最短路径

首先给出模板

#include<iostream>
#include<queue>
using namespace std;
const int INF = 100000000;
const int maxn = 10000;
typedef pair<int, int> P;	//储存坐标下x,y
int maze[maxn][maxn];
int d[maxn][maxn];			//储存每个坐标的最短路径
int sx, sy;					//起始坐标
int ex, ey;					//终点坐标
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };
int bfs()
{
	queue<P> que;			//bfs用队列
	for (int i = 0; i < maxn; i++) {		//初始化所有距离为极大
		for (int j = 0; j < maxn; j++) {
			d[i][j] = INF;
		}
	}
	que.push(P(sx, sy));
	d[sx][sy] = 0;
	while (que.size()) {
		P p = que.front();
		que.pop();
		if (p.first == ex && p.second == ey)
			break;
		for (int i = 0; i < 4; i++) {
			int nx = p.first + dx[i];
			int ny = p.second + dy[i];
			if (nx >= 0 && nx < N && ny >= 0 && ny < N && d[nx][ny] == INF && maze[nx][ny] == ) {
				que.push(P(nx, ny));
				d[nx][ny] = d[p.first][p.second] + 1;
			}
		}
	}
	return d[ex][ey];

例题

E - A计划

 HDU - 2102 

可怜的公主在一次次被魔王掳走一次次被骑士们救回来之后,而今,不幸的她再一次面临生命的考验。魔王已经发出消息说将在T时刻吃掉公主,因为他听信谣言说吃公主的肉也能长生不老。年迈的国王正是心急如焚,告招天下勇士来拯救公主。不过公主早已习以为常,她深信智勇的骑士LJ肯定能将她救出。 
现据密探所报,公主被关在一个两层的迷宫里,迷宫的入口是S(0,0,0),公主的位置用P表示,时空传输机用#表示,墙用*表示,平地用.表示。骑士们一进入时空传输机就会被转到另一层的相对位置,但如果被转到的位置是墙的话,那骑士们就会被撞死。骑士们在一层中只能前后左右移动,每移动一格花1时刻。层间的移动只能通过时空传输机,且不需要任何时间。

Input

输入的第一行C表示共有C个测试数据,每个测试数据的前一行有三个整数N,M,T。 N,M迷宫的大小N*M(1 <= N,M <=10)。T如上所意。接下去的前N*M表示迷宫的第一层的布置情况,后N*M表示迷宫第二层的布置情况。

Output

如果骑士们能够在T时刻能找到公主就输出“YES”,否则输出“NO”。

Sample Input

1
5 5 14
S*#*.
.#...
.....
****.
...#.

..*.P
#.*..
***..
...*.
*.#..

Sample Output

YES

唯一要数一的就是如果传送阵对面是墙或者传送阵的话我们当成墙来处理就好

AC代码

#include <bits/stdc++.h>
using namespace std;
int dis[4][2]={0,1,1,0,0,-1,-1,0};
int c,n,m,t,flag,i; 
struct node
{
	int x,y,z,step;
};
char mg[2][12][12];
bool cmp[2][12][12];
int  bfs(int a,int b,int c)
{
	memset(cmp,0,sizeof(cmp));
	queue<node> q;
	node pre,lst;
	pre.x=a;
	pre.y=b;
	pre.z=c;
	pre.step=0;
	cmp[pre.z][pre.x][pre.y]=1;
	q.push(pre);
	
	while(!q.empty())
	{
		pre=q.front();
		q.pop();
		//-------------------------
		if(mg[pre.z][pre.x][pre.y]=='P'&&pre.step<=t)
		{
			flag=1;
			return 0;
		 }
		 for(i=0;i<4;i++)
		 {
		 	lst.x=pre.x+dis[i][0];
		 	lst.y=pre.y+dis[i][1];
		 	lst.step=pre.step+1;
		 	// 时间过了,公主会被吃掉
            if( lst.step>t )   
				continue;
            // 下一步越界
            if( lst.x<0||lst.y<0||lst.x>=n||lst.y>=m )   
				continue;
            // 下一步走过或者撞墙
            if( mg[pre.z][lst.x][lst.y]=='*' || cmp[pre.z][lst.x][lst.y]==1 ) 
				continue;
            // 如果下一步到达传送阵
            if( mg[pre.z][lst.x][lst.y]=='#')
            {
                lst.z=(pre.z+1)%2;
                cmp[pre.z][lst.x][lst.y]=1;
                q.push(lst);
                continue;
            }
			cmp[pre.z][lst.x][lst.y]=1;
            lst.z=pre.z;
            q.push(lst);
		 }
	}
	return 0;	
}
int main()
{ 
 	cin>>c;
 	while(c--)
 	{
    	cin>>n>>m>>t;
 		for(int i=0;i<n;i++)
 			scanf("%s",mg[0][i]);
 		for(int i=0;i<n;i++)
 			scanf("%s",mg[1][i]);
 			
 		for(int i=0;i<n;i++)
 			for(int j=0;j<m;j++)//两端都是传送门,和一边是墙的情况我们都当成墙来处理 
 				if(mg[0][i][j]=='#'&&mg[1][i][j]=='#'||mg[0][i][j]=='#'&&mg[1][i][j]=='*'||mg[0][i][j]=='*'&&mg[1][i][j]=='#')
 				mg[0][i][j]=mg[1][i][j]='*';
 				
 		
		flag=0;
		bfs(0,0,0);
		if(flag)
		printf("YES\n");
		else
		printf("NO\n");	 
	 }
	return 0;
}

例二

F - 胜利大逃亡

 HDU - 1253 

Ignatius被魔王抓走了,有一天魔王出差去了,这可是Ignatius逃亡的好机会. 

魔王住在一个城堡里,城堡是一个A*B*C的立方体,可以被表示成A个B*C的矩阵,刚开始Ignatius被关在(0,0,0)的位置,离开城堡的门在(A-1,B-1,C-1)的位置,现在知道魔王将在T分钟后回到城堡,Ignatius每分钟能从一个坐标走到相邻的六个坐标中的其中一个.现在给你城堡的地图,请你计算出Ignatius能否在魔王回来前离开城堡(只要走到出口就算离开城堡,如果走到出口的时候魔王刚好回来也算逃亡成功),如果可以请输出需要多少分钟才能离开,如果不能则输出-1. 

Input

输入数据的第一行是一个正整数K,表明测试数据的数量.每组测试数据的第一行是四个正整数A,B,C和T(1<=A,B,C<=50,1<=T<=1000),它们分别代表城堡的大小和魔王回来的时间.然后是A块输入数据(先是第0块,然后是第1块,第2块......),每块输入数据有B行,每行有C个正整数,代表迷宫的布局,其中0代表路,1代表墙.(如果对输入描述不清楚,可以参考Sample Input中的迷宫描述,它表示的就是上图中的迷宫) 

特别注意:本题的测试数据非常大,请使用scanf输入,我不能保证使用cin能不超时.在本OJ上请使用Visual C++提交. 

Output

对于每组测试数据,如果Ignatius能够在魔王回来前离开城堡,那么请输出他最少需要多少分钟,否则输出-1. 

Sample Input

1
3 3 4 20
0 1 1 1
0 0 1 1
0 1 1 1
1 1 1 1
1 0 0 1
0 1 1 1
0 0 0 0
0 1 1 0
0 1 1 0

Sample Output

11

这个没什么特殊的就是多了几个方向

AC代码

#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
int a,b,c,t;
struct Coor
{
    int x,y,z,step;
};
int mapp[51][51][51],dis[6][3]={{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};
bool vis[51][51][51];
 
bool judge(int x,int y,int z)
{
    if(x<0 || y<0 || z<0 || x>=a || y>=b || z>=c)   return 0;
    if(vis[x][y][z] || mapp[x][y][z])   return 0;
    return 1;
}
 
int bfs(int x,int y,int z)
{
    queue <Coor> q;
    Coor pre,next;
    int i;
 
    pre.x=x;
    pre.y=y;
    pre.z=z;
    pre.step=0;
    vis[x][y][z]=1;
    q.push(pre);
 
    while(!q.empty())
    {
        pre=q.front();
        q.pop();
        if(pre.x==a-1 && pre.y==b-1 && pre.z==c-1)  return pre.step;
        if(pre.step>t)    return -1;
        for(i=0;i<6;++i)
        {
            next.x=pre.x+dis[i][0];
            next.y=pre.y+dis[i][1];
            next.z=pre.z+dis[i][2];
            if(judge(next.x,next.y,next.z))
            {
                next.step=pre.step+1;
                vis[next.x][next.y][next.z]=1;
 
                q.push(next);
            }
        }
    }
    return -1;
}
 
int main()
{
    int i,j,k,sl;
    scanf("%d",&sl);
    while(sl--)
    {
        scanf("%d%d%d%d",&a,&b,&c,&t);
        for(i=0;i<a;++i)
            for(j=0;j<b;++j)
                for(k=0;k<c;++k)
                    scanf("%d",&mapp[i][j][k]);
 
        memset(vis,0,sizeof(vis));
        printf("%d\n",bfs(0,0,0));
    }
    return 0;
}

例三

H - A strange lift

 HDU - 1548 

There is a strange lift.The lift can stop can at every floor as you want, and there is a number Ki(0 <= Ki <= N) on every floor.The lift have just two buttons: up and down.When you at floor i,if you press the button "UP" , you will go up Ki floor,i.e,you will go to the i+Ki th floor,as the same, if you press the button "DOWN" , you will go down Ki floor,i.e,you will go to the i-Ki th floor. Of course, the lift can't go up high than N,and can't go down lower than 1. For example, there is a buliding with 5 floors, and k1 = 3, k2 = 3,k3 = 1,k4 = 2, k5 = 5.Begining from the 1 st floor,you can press the button "UP", and you'll go up to the 4 th floor,and if you press the button "DOWN", the lift can't do it, because it can't go down to the -2 th floor,as you know ,the -2 th floor isn't exist. 
Here comes the problem: when you are on floor A,and you want to go to floor B,how many times at least he has to press the button "UP" or "DOWN"? 

Input

The input consists of several test cases.,Each test case contains two lines. 
The first line contains three integers N ,A,B( 1 <= N,A,B <= 200) which describe above,The second line consist N integers k1,k2,....kn. 
A single 0 indicate the end of the input.

Output

For each case of the input output a interger, the least times you have to press the button when you on floor A,and you want to go to floor B.If you can't reach floor B,printf "-1".

Sample Input

5 1 5
3 3 1 2 5
0

Sample Output

3

题目大意

有一部电梯,它在固定的层数只能上升或下降固定的层数

用广搜一步步模拟很容易的

AC代码

#include<bits/stdc++.h> 
using namespace std;
int n,a,b;
int k[205];//存储上行或下行的层数 
bool cmp[205];//是否来过 
struct node
{
	int left,step;
	//记录走了几步 
};
int bfs()
{
	queue<node>q;
	memset(cmp,0,sizeof(cmp));
	node pre,lst;
	//第一个点入队
	pre.left=a;
	pre.step=0;
	cmp[pre.left]=1;
	q.push(pre);
	
	while(!q.empty())
	{
		pre=q.front();
		q.pop();
		if(pre.left==b)
		return pre.step;
		//向下 
		lst.left=pre.left-k[pre.left];
		if(lst.left>0&&lst.left<=n&&cmp[lst.left]!=1)
		{
			lst.step=pre.step+1;
			cmp[pre.left]=1;
			q.push(lst);
		}
		//向上
		lst.left=pre.left+k[pre.left];
		if(lst.left>0&&lst.left<=n&&cmp[lst.left]!=1)
		{
			lst.step=pre.step+1;
			k[pre.left]=1;
			q.push(lst);
		}
	}
	return -1;
}

int main(){
   	while(cin>>n>>a>>b&&n!=0)
   	{
   		for(int i=1;i<=n;i++)
   		cin>>k[i];
   		cout<<bfs()<<endl;
	}
	return 0;
}

例四

I - Catch That Cow

 HDU - 2717 

Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer John has two modes of transportation: walking and teleporting. 

* Walking: FJ can move from any point X to the points X - 1 or X + 1 in a single minute 
* Teleporting: FJ can move from any point X to the point 2 × X in a single minute. 

If the cow, unaware of its pursuit, does not move at all, how long does it take for Farmer John to retrieve it?

Input

Line 1: Two space-separated integers: N and K

Output

Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.

Sample Input

5 17

Sample Output

4


        
  

Hint

The fastest way for Farmer John to reach the fugitive cow is to move along the following path: 5-10-9-18-17, which takes 4 minutes.
        
 题意

强子的牛跑了,他要去把牛抓回来,输入两个数,一个是强子的位置,一个是牛的位置,强子每一次可以向前走一格

也可以向后走一格,或者直接传送到2x的位置

分析

因为本题中牛的位置是不动的,所以我们可以理解为最短路径问题

AC代码

#include <bits/stdc++.h>
using namespace std;
#define maxn 200010
int n,k,ans;
bool  cmp[maxn];
struct node
{
	int n;
	int x;
};
int bfs(int start)
{
	queue<node> q;
	node lst,flag;
	memset(cmp,0,sizeof(cmp));
	lst.n=start;
	lst.x=0;
	cmp[lst.n]=1;
	q.push(lst);
	while(!q.empty())
	{
		lst=q.front();
		q.pop();
		for(int i=0;i<3;i++)
		{
		
			if(i == 0)
            {
                flag.n = lst.n + 1;//进一步 
            }
            if(i == 1)
            {
                flag.n = lst.n - 1;//退一步 
            }
            if(i == 2)
            {
                flag.n =lst.n * 2;//传送 
            }
            flag.x=lst.x+1;
            if(flag.n>=0&&flag.n<=100000&&cmp[flag.n]!=1)
            {
            	if(flag.n==k)
            	return flag.x;
            	cmp[flag.n]=1;
            	q.push(flag);
			}
		}
	}
}
int main()
{   ans=0;
    while(cin>>n>>k) 
    {
		if(n==k)
		{
			printf("0\n");
			continue;
		}
		cout<<bfs(n)<<endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42105529/article/details/81482753