********广度优先搜索*********
目录
BFS算法:
广度优先搜索算法
POJ 3278 Catch That Cow
百练 4116:拯救行动
BFS算法:
思路:
1.从初始状态S开始,利用规则,生成下一层的状态。
2.顺序检查下一层的所有状态,看是否出现目标状态G。
否则就对该层所有状态节点,分别利用规则。生成再下一层的所有状态节点。
3.继续按照上面思想生成下一层的所有状态节点,这样一层一层往下展开。
直到出现目标状态为止
先遍历离起点近的,再到远的,网上有一个很形象的例子:你的眼镜掉在地上以后,你趴在地板上找。你总是先摸离你最近的地方,如果没有,再摸距离较远的地方。
通常用队列来实现
初始化队列Q
Q={起点s};
标记s为已访问;
while(Q非空)
{
取Q队首元素u;
u出队;
if(u==目标状态)
{.............}
所有与u相邻且未被访问的点进入队列;
标记u为已访问;
}
广度优先搜索算法如下:(用 QUEUE )
(1) 把初始节点 S0 放入 Open 表中;
(2) 如果 Open 表为空,则问题无解失败 退出;
(3) 把Open 表的第一个节点取出放入 Closed 表,并记该节点为 n;
(4) 考察节点 n是否为目标节点。若, 则得到问题的解,成功退出;
(5) 若节点 n不可扩展,则转第 (2) 步;
(6) 扩展节点 n,将其不在 Closed 表和 Open 表中的子节点 (判重) 放入 Open 表的尾部 ,并为每一个子节点设置指向父的针 (或记录节点的层次) ,然后转第 (2) 步
这个网址有BFS例子具体的实现过程:
BFS的具体实现过程
POJ 3278 Catch That Cow
Description
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.
Source
USACO 2007 Open Silver
北大课件代码:
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
const int maxn=1e5;
int n,k;
int vis[maxn+10];
struct step
{int x;int steps;step(int xx,int s):x(xx),steps(s){ }
};
queue<step>Q;
void bfs()
{while(!Q.empty()){step s=Q.front();if(s.x==k){cout<<s.steps<<endl;return ;}else{if(s.x-1>=0 && !vis[s.x-1]){Q.push(step(s.x-1,s.steps+1));vis[s.x-1]=1;}if(s.x+1<=maxn && !vis[s.x+1])//步数小于maxn{Q.push(step(s.x+1,s.steps+1));vis[s.x+1]=1;}if(s.x*2<=maxn && !vis[s.x*2])//步数小于maxn{Q.push(step(s.x*2,s.steps+1));vis[s.x*2]=1;}Q.pop();}}return ;
}
int main()
{cin>>n>>k;memset(vis,0,sizeof(vis));Q.push(step(n,0));vis[n]=1;bfs();return 0;
}
注意:
1.s.x+1<=maxn,s.x*2<=maxn。
自己之前代码:
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
const int maxn=200100;//注意这个地方的取值,maxn=1e5+100 POJ上交 Runtime Error
struct Node
{
int x;
int step;
};
int n,k;
int vis[maxn];
queue<Node>Q;
void bfs()
{while(!Q.empty()){Node w2=Q.front();Q.pop();int x=w2.x;int step=w2.step;if(x==k){cout<<step<<endl;return ;}if(x<=k && !vis[x+1]){Node w3;vis[x+1]=1;w3.x=x+1;w3.step=step+1;Q.push(w3);}if(x>=1 && !vis[x-1]){Node w3;vis[x-1]=1;w3.x=x-1;w3.step=step+1;Q.push(w3);}if(x<=k && !vis[2*x]){Node w3;vis[2*x]=1;w3.x=x*2;w3.step=step+1;Q.push(w3);}}
}
int main()
{while(scanf("%d%d",&n,&k)!=EOF){while(!Q.empty())Q.pop();memset(vis,0,sizeof(vis));vis[n]=1;Node w1;w1.x=n;w1.step=0;Q.push(w1);bfs();}return 0;
}
百练 4116:拯救行动
描述
公主被恶人抓走,被关押在牢房的某个地方。牢房用N*M (N, M <= 200)的矩阵来表示。矩阵中的每项可以代表道路(@)、墙壁(#)、和守卫(x)。
英勇的骑士(r)决定孤身一人去拯救公主(a)。我们假设拯救成功的表示是“骑士到达了公主所在的位置”。由于在通往公主所在位置的道路中可能遇到守卫,骑士一旦遇到守卫,必须杀死守卫才能继续前进。
现假设骑士可以向上、下、左、右四个方向移动,每移动一个位置需要1个单位时间,杀死一个守卫需要花费额外的1个单位时间。同时假设骑士足够强壮,有能力杀死所有的守卫。
给定牢房矩阵,公主、骑士和守卫在矩阵中的位置,请你计算拯救行动成功需要花费最短时间。
输入
第一行为一个整数S,表示输入的数据的组数(多组输入)
随后有S组数据,每组数据按如下格式输入
1、两个整数代表N和M, (N, M <= 200).
2、随后N行,每行有M个字符。"@"代表道路,"a"代表公主,"r"代表骑士,"x"代表守卫, "#"代表墙壁。
输出
如果拯救行动成功,输出一个整数,表示行动的最短时间。
如果不可能成功,输出"Impossible"
样例输入
2
7 8
#@#####@
#@a#@@r@
#@@#x@@@
@@#@@#@#
#@@@##@@
@#@@@@@@
@@@@@@@@
13 40
@x@@##x@#x@x#xxxx##@#x@x@@#x#@#x#@@x@#@x
xx###x@x#@@##xx@@@#@x@@#x@xxx@@#x@#x@@x@
#@x#@x#x#@@##@@x#@xx#xxx@@x##@@@#@x@@x@x
@##x@@@x#xx#@@#xxxx#@@x@x@#@x@@@x@#@#x@#
@#xxxxx##@@x##x@xxx@@#x@x####@@@x#x##@#@
#xxx#@#x##xxxx@@#xx@@@x@xxx#@#xxx@x#####
#x@xxxx#@x@@@@##@x#xx#xxx@#xx#@#####x#@x
xx##@#@x##x##x#@x#@a#xx@##@#@##xx@#@@x@x
x#x#@x@#x#@##@xrx@x#xxxx@##x##xx#@#x@xx@
#x@@#@###x##x@x#@@#@@x@x@@xx@@@@##@@x@@x
x#xx@x###@xxx#@#x#@@###@#@##@x#@x@#@@#@@
#@#x@x#x#x###@x@@xxx####x@x##@x####xx#@x
#x#@x#x######@@#x@#xxxx#xx@@@#xx#x#####@
样例输出
13
7
一开始做这个题目的时候,觉得像 Catch That Cow,只不过多计算了步数而已,所以我就用了普通队列,按照上下左右四个方向走,是守卫步数就+2,是通道步数就+1,但是我忘记考虑了一个问题,在走有守卫和通道这两种选择上,应该选择步数最少了,所以应该用优先队列。.
自己代码:
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
const int maxn=250;
struct Node
{int x;int y;int step;bool operator<(const Node &n)const{return step>n.step;}
};
char g[maxn][maxn];
int n,m;
int u,v;
int vis[maxn][maxn];
int dir[4][2]={1,0,0,1,-1,0,0,-1};
priority_queue<Node>Q;
void bfs()
{Node now,last;while(!Q.empty()){last=Q.top();Q.pop();int x=last.x;int y=last.y;int step=last.step;for(int i=0;i<4;i++){now.x=x+dir[i][0];now.y=y+dir[i][1];if(now.x>=0 && now.x<n && now.y>=0 && now.y<m && !vis[now.x][now.y] && g[now.x][now.y]!='#'){if(g[now.x][now.y]=='x'){Node w1;w1.x=now.x;w1.y=now.y;w1.step=step+2;vis[now.x][now.y]=1;Q.push(w1);}if(g[now.x][now.y]=='@'){Node w1;w1.x=now.x;w1.y=now.y;w1.step=step+1;vis[now.x][now.y]=1;Q.push(w1);}if(g[now.x][now.y]=='a') //如果找到公主的位置,步数+1,然后输出即可{printf("%d\n",step+1);return ;}}}}cout<<"Impossible"<<endl;
}
int main()
{int S;while(scanf("%d",&S)!=EOF){while(S--){scanf("%d%d",&n,&m);memset(vis,0,sizeof(vis));while(!Q.empty())Q.pop();for(int i=0;i<n;i++){scanf("%s",g[i]);}for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(g[i][j]=='r'){Node t;t.x=i;t.y=j;t.step=0;vis[i][j]=1;Q.push(t);}if(g[i][j]=='a'){u=i;v=j;}}}bfs();}}return 0;
}
错误代码:没有把公主的坐标放进队列
void bfs()
{Node now,last;while(!Q.empty()){last=Q.top();Q.pop();int x=last.x;int y=last.y;int step=last.step;printf("x=%d y=%d\n",x,y);if(x==u && y==v)//公主坐标不在队列中,所以永远不会执行这一句if语句,也就不会输出步数{printf("%d\n",step);return ; }for(int i=0;i<4;i++){now.x=x+dir[i][0];now.y=y+dir[i][1];if(now.x>=0 && now.x<n && now.y>=0 && now.y<m && !vis[now.x][now.y] && g[now.x][now.y]!='#'){if(g[now.x][now.y]=='x'){Node w1;w1.x=now.x;w1.y=now.y;w1.step=step+2;vis[now.x][now.y]=1;Q.push(w1);}if(g[now.x][now.y]=='@'){Node w1;w1.x=now.x;w1.y=now.y;w1.step=step+1;vis[now.x][now.y]=1;Q.push(w1);}}}}cout<<"Impossible"<<endl;
}
注意:
1.一开始只判断了骑士走的是道路还是 守卫,并没有判断公主的位置,找到通道和守卫的位置,记录坐标和步数,放进队列,找到公主的位置也应该记录坐标的和步数,这样在另一层循环的时候取队头,取到公主的坐标,才能进入if语句输出步数。
课件代码:
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
const int maxn=250;
struct Node
{int x;int y;int step;bool operator<(const Node &f)const{//重载的小于运算符 在push/top中用到了return step>f.step;//最小值优先}Node(int xx,int yy,int ss):x(xx),y(yy),step(ss){ }//给x,y,step不算赋值
};
char g[maxn][maxn];
int n,m;
int u,v;
int vis[maxn][maxn];
int dir[4][2]={1,0,0,1,-1,0,0,-1};
priority_queue<Node>Q;
void bfs()
{while(!Q.empty()){int hx=Q.top().x;int hy=Q.top().y;int hs=Q.top().step;Q.pop();//vis[hx][hy]=1;// printf("hx= %d hy=%d hs=%d\n",hx,hy,hs);if(hx==u && hy==v){printf("%d\n",hs);return ;}for(int i=0;i<4;i++){int nowx=hx+dir[i][0];int nowy=hy+dir[i][1];if(nowx>=0 && nowx<n && nowy>=0 && nowy<m && !vis[nowx][nowy] && g[nowx][nowy]!='#'){if(g[nowx][nowy]=='x'){Q.push(Node(nowx,nowy,hs+2));}else{Q.push(Node(nowx,nowy,hs+1));}vis[nowx][nowy]=1;}}}cout<<"Impossible"<<endl;
}
int main()
{int S;while(scanf("%d",&S)!=EOF){while(S--){memset(vis,0,sizeof(vis));while(!Q.empty())Q.pop();scanf("%d%d",&n,&m);for(int i=0;i<n;i++)scanf("%s",g[i]);for(int i=0;i<n;i++) {for(int j=0;j<m;j++){if(g[i][j]=='r'){// printf("i=%d j=%d\n",i,j);vis[i][j]=1;Q.push(Node(i,j,0));}if(g[i][j]=='a'){//printf("u=%d v=%d\n",u,v);u=i;v=j;}}}bfs();}}return 0;
}
注意:
1.g[i][j]=='a', 两个等于号,不要漏掉。
2.使用优先队列。
4115:鸣人和佐助
描述
佐助被大蛇丸诱骗走了,鸣人在多少时间内能追上他呢?
已知一张地图(以二维矩阵的形式表示)以及佐助和鸣人的位置。地图上的每个位置都可以走到,只不过有些位置上有大蛇丸的手下,需要先打败大蛇丸的手下才能到这些位置。鸣人有一定数量的查克拉,每一个单位的查克拉可以打败一个大蛇丸的手下。假设鸣人可以往上下左右四个方向移动,每移动一个距离需要花费1个单位时间,打败大蛇丸的手下不需要时间。如果鸣人查克拉消耗完了,则只可以走到没有大蛇丸手下的位置,不可以再移动到有大蛇丸手下的位置。佐助在此期间不移动,大蛇丸的手下也不移动。请问,鸣人要追上佐助最少需要花费多少时间?
输入
输入的第一行包含三个整数:M,N,T。代表M行N列的地图和鸣人初始的查克拉数量T。0 < M,N < 200,0 ≤ T < 10
后面是M行N列的地图,其中@代表鸣人,+代表佐助。*代表通路,#代表大蛇丸的手下。
输出
输出包含一个整数R,代表鸣人追上佐助最少需要花费的时间。如果鸣人无法追上佐助,则输出-1。
样例输入
样例输入1
4 4 1
#@##
**##
###+
****样例输入2
4 4 2
#@##
**##
###+
****
样例输出
样例输出1
6样例输出2
4
多一个判断查克拉的数组,因此要多一步
问题代码: 两种方式均没有记录查克拉。
/*
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
const int maxn=250;
int n,m,t;
int u,v;
struct Node
{int x;int y;int minute;int ckl;Node(int xx,int yy,int mm,int cc): x(xx),y(yy),minute(mm),ckl(cc){ }
};
char g[maxn][maxn];
int vis[maxn][maxn];
int dir[4][2]={1,0,0,1,-1,0,0,-1};
queue<Node>Q;
void bfs()
{while(!Q.empty()){int hx=Q.front().x;int hy=Q.front().y;int hm=Q.front().minute;int hc=Q.front().ckl;if(hx==u && hy==v){printf("%d\n",hm);return ;}for(int i=0;i<4;i++){int nx=hx+dir[i][0];int ny=hy+dir[i][1];if(nx>=0 && nx<m&&ny>=0&& ny<n&&!vis[nx][ny]){if(g[nx][ny]=='*'){Q.push(nx,ny,hm+1,hc);}if(g[nx][ny]=='#'&&hc>0){Q.push(nx,ny,hm+1,hc-1);}if(g[nx][ny]=='+'){Q.push(nx,ny,hm+1,hc)}}}}puts("-1");
}
int main()
{scanf("%d%d%d",&m,&n,&t);memset(vis,0,sizeof(vis));while(!Q.empty())Q.pop();for(int i=0;i<m;i++){scanf("%s",g[i]);}for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(g[i][j]=='@'){// printf("i=%d j=%d\n",i,j);vis[i][j]=1;Q.push(Node(i,j,0,t));}if(g[i][j]=='+'){u=i;v=j;// printf("u=%d v=%d\n",u,v);}}}bfs(); return 0;
}
*/#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
const int maxn=250;
int n,m,t;
int u,v;
struct Node
{int x;int y;int minute;int ckl;
};
char g[maxn][maxn];
int vis[maxn][maxn][maxn];
int dir[4][2]={1,0,0,1,-1,0,0,-1};
queue<Node>Q;
void bfs()
{Node now,last;while(!Q.empty()){last=Q.front();Q.pop();int hx=last.x;int hy=last.y;int hm=last.minute;int ht=last.ckl;if(hx==u && hy==v){printf("%d\n",hm);return ;}for(int i=0;i<4;i++){now.x=hx+dir[i][0];now.y=hy+dir[i][1];if(now.x>=0 && now.x<m && now.y>=0 && now.y<n){if(g[now.x][now.y]=='#' && !vis[now.x][now.y][now.ckl] && now.ckl>0){Node w1;w1.x=now.x;w1.y=now.y;w1.minute=now.minute+1;w1.ckl=now.ckl-1;Q.push(w1);vis[now.x][now.y][now.ckl]=1;}if(g[now.x][now.y]!='#' && !vis[now.x][now.y][now.ckl] ){Node w1;w1.x=now.x;w1.y=now.y;w1.minute=now.minute+1;w1.ckl=now.ckl; Q.push(w1);vis[now.x][now.y][now.ckl]=1;}}}}puts("-1");
}
int main()
{scanf("%d%d%d",&m,&n,&t);memset(vis,0,sizeof(vis));while(!Q.empty())Q.pop();for(int i=0;i<m;i++){scanf("%s",g[i]);}for(int i=0;i<m;i++){for(int j=0;j<n;j++){ if(g[i][j]=='@'){Node w;w.x=i;w.y=j;w.minute=0;w.ckl=t;vis[i][j][t]=1;Q.push(w);}if(g[i][j]=='+'){u=i;v=j;}}}bfs(); return 0;
}
注意:
1.二维数组的读入方式。不确定可以先输出看看是否正确。
********广度优先搜索*********相关推荐
- [C] 层层递进——C语言实现广度优先搜索
以防万一有人想不开要做染色的题呢?比如我. 广度优先搜索 如何实现一个广度优先搜索 广搜(bfs)是一个层层递进的概念,与深搜的不撞南墙不回头不同,广搜更像一个感染的过程,一个点只能感染到它周边的点. ...
- python扫雷 广度优先_Leetcode之广度优先搜索(BFS)专题-529. 扫雷游戏(Minesweeper)...
Leetcode之广度优先搜索(BFS)专题-529. 扫雷游戏(Minesweeper) BFS入门详解:Leetcode之广度优先搜索(BFS)专题-429. N叉树的层序遍历(N-ary Tre ...
- 初识广度优先搜索与解题套路
作者 | P.yh 来源 | 五分钟学算法 初识广度优先搜索 在讲解广度优先搜索之前,我们来看看几个常见的数据结构,链表.树.图. 先来看看其中比较简单的数据结构 - 链表,它和数组类似,也是一个线性 ...
- matlab bfs函数,matlab练习程序(广度优先搜索BFS、深度优先搜索DFS)
如此经典的算法竟一直没有单独的实现过,真是遗憾啊. 广度优先搜索在过去实现的二值图像连通区域标记和prim最小生成树算法时已经无意识的用到了,深度优先搜索倒是没用过. 这次单独的将两个算法实现出来,因 ...
- networkx 有向图强连通_leetcode刷题(四):搜索(深度优先搜索,广度优先搜索)拓扑排序,强连通分量...
在开始今天的话题之前,我们先了解一个概念,什么是图的遍历? 图的遍历就是从图中某一点出发访遍图中其余剩余定点,且每个顶点仅被访问一次,这个过程叫做图的遍历. 图的遍历主要被分为深度优先遍历和广度优先遍 ...
- LeetCode-笔记-199. 二叉树的右视图——BFS广度优先搜索
LeetCode-笔记-199. 二叉树的右视图 199. 二叉树的右视图 给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值. 示例: 输入: [1,2,3,n ...
- 根据邻接表求深度优先搜索和广度优先搜索_深度优先搜索/广度优先搜索与java的实现...
度:某个顶点的度就是依附于该顶点的边的个数 子图:一幅图中所有边(包含依附边的顶点)的子集 路径:是由边顺序连接的一系列定点组成 环:至少含有一条边且终点和起点相同的路径 连通图:如果图中任一个到另一 ...
- 图的遍历——广度优先搜索(Breadth First Search)
2019独角兽企业重金招聘Python工程师标准>>> 1.广度优先搜索遍历类似于树的按层次遍历的过程. 假设从图中某顶点V出发,在访问了V之后依次访问V的各个未曾访问过得邻接点,然 ...
- 地牢逃脱(BFS(广度优先搜索))
题目描述 给定一个 n 行 m 列的地牢,其中 '.' 表示可以通行的位置,'X' 表示不可通行的障碍,牛牛从 (x0 , y0 ) 位置出发,遍历这个地牢,和一般的游戏所不同的是,他每一步只能按照一 ...
- 用BFS(广度优先搜索queuelist)算法解决农夫过河问题
用BFS(广度优先搜索queue&&list)算法解决农夫过河问题 一.问题需求分析 一个农夫带着一只狼.一只羊和一棵白菜,身处河的南岸.他要把这些东西全部运到北岸.问题是他面前只有一 ...
最新文章
- 详解 CSS 属性 - 伪类和伪元素的区别
- spring事物配置,声明式事务管理和基于@Transactional注解的使用
- JVM源码—教你傻瓜式编译openjdk7
- xmldocument如何创建一个不带结尾的节点_LDF文件是个啥?如何创建一个LDF文件
- 技术干货 | jsAPI 方式下的导航栏的动态化修改
- Mysql 监控小脚本
- Decorator(装饰)--对象结构型模式
- 倒叙输出 php,php foreach正序倒序输出示例代码
- 【小技巧】【Java】 创建指定数目m的Set数组
- [剑指offer][JAVA]面试题第[04]题[二维数中的查找][数组]
- BugkuCTF-MISC题一切有为法如梦幻泡影
- JS实现监控微信小程序
- Spring框架中级联赋值(外部属性注入)以及内部属性注入
- RefreshParenwin 打开子窗体 并回发
- java 置位_java安全编码指南之:Mutability可变性详解
- atitit. 浏览器插件 控件 applet 的部署,签名总结 浏览器 插件 控件 的签名安全机制o9o
- PHP在线讨饭源码+支付宝当面付DEMO+自动在线要饭源码+安装教程
- 音视频同步、网络抖动
- 关于基本勾股数规律的探讨总结与例题!
- 【CSDN年度之“战”征文】机器学习该怎么学?