目录

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 - 1 or + 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.二维数组的读入方式。不确定可以先输出看看是否正确。

********广度优先搜索*********相关推荐

  1. [C] 层层递进——C语言实现广度优先搜索

    以防万一有人想不开要做染色的题呢?比如我. 广度优先搜索 如何实现一个广度优先搜索 广搜(bfs)是一个层层递进的概念,与深搜的不撞南墙不回头不同,广搜更像一个感染的过程,一个点只能感染到它周边的点. ...

  2. python扫雷 广度优先_Leetcode之广度优先搜索(BFS)专题-529. 扫雷游戏(Minesweeper)...

    Leetcode之广度优先搜索(BFS)专题-529. 扫雷游戏(Minesweeper) BFS入门详解:Leetcode之广度优先搜索(BFS)专题-429. N叉树的层序遍历(N-ary Tre ...

  3. 初识广度优先搜索与解题套路

    作者 | P.yh 来源 | 五分钟学算法 初识广度优先搜索 在讲解广度优先搜索之前,我们来看看几个常见的数据结构,链表.树.图. 先来看看其中比较简单的数据结构 - 链表,它和数组类似,也是一个线性 ...

  4. matlab bfs函数,matlab练习程序(广度优先搜索BFS、深度优先搜索DFS)

    如此经典的算法竟一直没有单独的实现过,真是遗憾啊. 广度优先搜索在过去实现的二值图像连通区域标记和prim最小生成树算法时已经无意识的用到了,深度优先搜索倒是没用过. 这次单独的将两个算法实现出来,因 ...

  5. networkx 有向图强连通_leetcode刷题(四):搜索(深度优先搜索,广度优先搜索)拓扑排序,强连通分量...

    在开始今天的话题之前,我们先了解一个概念,什么是图的遍历? 图的遍历就是从图中某一点出发访遍图中其余剩余定点,且每个顶点仅被访问一次,这个过程叫做图的遍历. 图的遍历主要被分为深度优先遍历和广度优先遍 ...

  6. LeetCode-笔记-199. 二叉树的右视图——BFS广度优先搜索

    LeetCode-笔记-199. 二叉树的右视图 199. 二叉树的右视图 给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值. 示例: 输入: [1,2,3,n ...

  7. 根据邻接表求深度优先搜索和广度优先搜索_深度优先搜索/广度优先搜索与java的实现...

    度:某个顶点的度就是依附于该顶点的边的个数 子图:一幅图中所有边(包含依附边的顶点)的子集 路径:是由边顺序连接的一系列定点组成 环:至少含有一条边且终点和起点相同的路径 连通图:如果图中任一个到另一 ...

  8. 图的遍历——广度优先搜索(Breadth First Search)

    2019独角兽企业重金招聘Python工程师标准>>> 1.广度优先搜索遍历类似于树的按层次遍历的过程. 假设从图中某顶点V出发,在访问了V之后依次访问V的各个未曾访问过得邻接点,然 ...

  9. 地牢逃脱(BFS(广度优先搜索))

    题目描述 给定一个 n 行 m 列的地牢,其中 '.' 表示可以通行的位置,'X' 表示不可通行的障碍,牛牛从 (x0 , y0 ) 位置出发,遍历这个地牢,和一般的游戏所不同的是,他每一步只能按照一 ...

  10. 用BFS(广度优先搜索queuelist)算法解决农夫过河问题

    用BFS(广度优先搜索queue&&list)算法解决农夫过河问题 一.问题需求分析 一个农夫带着一只狼.一只羊和一棵白菜,身处河的南岸.他要把这些东西全部运到北岸.问题是他面前只有一 ...

最新文章

  1. 详解 CSS 属性 - 伪类和伪元素的区别
  2. spring事物配置,声明式事务管理和基于@Transactional注解的使用
  3. JVM源码—教你傻瓜式编译openjdk7
  4. xmldocument如何创建一个不带结尾的节点_LDF文件是个啥?如何创建一个LDF文件
  5. 技术干货 | jsAPI 方式下的导航栏的动态化修改
  6. Mysql 监控小脚本
  7. Decorator(装饰)--对象结构型模式
  8. 倒叙输出 php,php foreach正序倒序输出示例代码
  9. 【小技巧】【Java】 创建指定数目m的Set数组
  10. [剑指offer][JAVA]面试题第[04]题[二维数中的查找][数组]
  11. BugkuCTF-MISC题一切有为法如梦幻泡影
  12. JS实现监控微信小程序
  13. Spring框架中级联赋值(外部属性注入)以及内部属性注入
  14. RefreshParenwin 打开子窗体 并回发
  15. java 置位_java安全编码指南之:Mutability可变性详解
  16. atitit. 浏览器插件 控件 applet 的部署,签名总结 浏览器 插件 控件 的签名安全机制o9o
  17. PHP在线讨饭源码+支付宝当面付DEMO+自动在线要饭源码+安装教程
  18. 音视频同步、网络抖动
  19. 关于基本勾股数规律的探讨总结与例题!
  20. 【CSDN年度之“战”征文】机器学习该怎么学?

热门文章

  1. 用Python下载煎蛋网全站好看的小姐姐!
  2. GOCI数据批量下载
  3. win10声音显示红叉问题解决
  4. 四选一多路开关电路描述
  5. 2022牛客寒假算法基础集训营5 E.复苏小孩 详解
  6. Ubuntu息屏后唤醒的花屏问题
  7. 笔记本计算机待机后显示器,笔记本电脑休眠后一直黑屏怎么回事_笔记本休眠后屏幕一直黑屏无法唤醒如何解决-win7之家...
  8. 从屏下指纹到体感手机,vivo能否走出自己的创新之路?
  9. 什么是内聚?什么是耦合?
  10. Axure如何填充背景图