之前也写过一些广搜,但是我只知其形,不知其意,今天我们通过三份代码的比较从这两个方面来谈谈广度优先搜索
第一份代码:二叉树BFS遍历(博客上有)
第二份代码:poj3278,农夫找牛,
第三份代码:天神小学,我之前的的博客上有
通过比较,我们来感受一下广搜的形!!!
显然,广搜是用队列来实现的,通过先进先出的这种特点来实现算法
我总结了一下BFS的大体结构(形)
1.声明一个队列Q,一般为代码中的结构体类型,我比较喜欢用全局变量,这样BFS函数不需要形式参数,而且大家有没有发现,一般main函数里调用了BFS后,基本就要return 0; 了
2.声明两个结构体对象
3.将起始点进行标记
4.用起始点的参数来初始化其中一个结构体对象
5.将初始化的对象入队
6.来个while循环,一旦队列为空
7.接着是while循环内部
8首先将队首元素赋给初始化的对象(记得刚开始学广搜时搞不明白这个地方,为什么要来这么一句,当手工模拟一遍程序运行时我大约就模模糊糊的理解了)
9.让队首元素出队
10.判断是否满足题目要求搜索的地方,如果满足,结束搜索
11.进行各个方向的搜索,一旦搜索到没有搜索的地方,将其入队,并标记已经搜索过(想一想为什么要标记呢,不标记的话OJ可能会返回memory limit exceed,)
12.判断队列是否为空
好啦,BFS的结构大约就是这样子的,大家可不能死记硬背,我们要来思考一下其背后的意义
BFS的背后的意(主要谈谈我认为两个稍微有点难理解地方的)
感觉这篇博客最考验我的时候来到了,我的脑细胞又要开始想着到底怎么把只可意会不可言传的那种状态抹杀掉,其实这也是我写博客最大的动力,逼着自己去思考,去认认真真理解,不是模模糊糊理解个大概
我们先来谈谈为什么要声明两个结构体对象(第一份代码不需要两个,但还是手残写了两个),第一个结构体对象用来盛放队首元素,然后第二个对象以第一个对象为基础向题目允许的方向进行搜索,然后将搜索的结果存储到队列中(感觉讲的云里雾里,但我保证,大家在完全独立的情况下将第三份代码敲上几遍再来看看就会很有感觉)
接着我们来谈谈为什么标记,其实标记就是把进队过的元素进行标记,假如我们不标记,一旦搜索到,我们还会将其进队,显然这个元素刚才已经进过队,假如再次进队,那么就会重复刚才的搜索过程,显然就会大量重复,大家可以用gdb调试看看就能感受到,假设没有标记的话,,编译运行输入数据后你的电脑风扇就得呼呼转了
第一份代码
#include <iostream>
#include <queue>
using namespace std;
struct Node
{
Node *Left;
int Value;
Node *Right;
Node(int value=0, Node *left=NULL, Node *right=NULL):Value(value) , Left(left), Right(right) {};
};
bool flag=true;
Node *node[11];
void creat();
void BFS(Node*);
int main()
{
creat();
Node* Root = node[10];
cout<<"广搜结果为:"<<endl;
BFS(Root);
return 0;
}
void creat()
{
node[1]=new Node(1);
node[2]=new Node(2);
node[3]=new Node(3);
node[4]=new Node(4);
node[5]=new Node(5, node[1], node[2]);
node[6]=new Node(6, node[3], node[4]);
node[7]=new Node(7);
node[8]=new Node(8,node[5],node[6]);
node[9]=new Node(9,node[7]);
node[10]=new Node(10,node[8],node[9]);
}
void BFS(Node*)
{
queue<Node*> Q;
Node* a,b;
a=node[10];
Q.push(a);
while(!Q.empty())
{
a=Q.front();
Q.pop();
cout<<a->Value<<" ";
if(a->Left!=NULL)
Q.push(a->Left);
if(a->Right!=NULL)
Q.push(a->Right);
}
return;
}
第二份代码 题目:POJ3278
Catch That Cow
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 69402 Accepted: 21819
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.
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.
代码:
#include <iostream>
#include <cstring>
#include <queue>
#define lim 1000000
using namespace std;
struct Node
{
int x;
int step;
};
int n, k, res;
int Map[lim+10];
bool jude(int);
void bfs();
int main()
{
memset(Map, 0, sizeof(Map));
cin>>n>>k;
bfs();
cout<<res<<endl;
return 0;
}
bool jude(int x)
{
if(x<0||x>lim+2||Map[x])
return false;
return true;
}
void bfs()
{
queue<Node> Q;
Node a, b;
Map[n]=1;
a.x=n;
a.step=0;
Q.push(a);
while(!Q.empty())
{
a=Q.front();
Q.pop();
if(a.x==k)
{
res=a.step;
return;
}
b.x=a.x+1;
if(jude(b.x))
{
b.step=a.step+1;
Map[b.x]=1;
Q.push(b);
}
b.x=a.x-1;
if(jude(b.x))
{
b.step=a.step+1;
Map[b.x]=1;
Q.push(b);
}
b.x=a.x*2;
if(jude(b.x))
{
b.step=a.step+1;
Map[b.x]=1;
Q.push(b);
}
}
}
第三份代码 题目我之前的博客有
#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int lim=50;
int dirx[4]= {-1, 1, 0, 0};
int diry[4]= {0, 0, -1, 1};
int row, col;
char Map[lim][lim];
int vis[lim][lim];
char str[lim];
int xru, yru, xchu, ychu;
typedef struct
{
int x;
int y;
int step;
} point;
void bfs();
int main()
{
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
int T, i, j;
cin>>T;
while(T--)
{
cin>>row>>col;
memset(str, 0, sizeof(str));
memset(Map, 0, sizeof(Map));
memset(vis, 0, sizeof(vis));
for(i=1; i<=row; i++)
{
scanf("%s", str);
for(j=1; j<=col; j++)
Map[i][j]=str[j-1];
}
for(i=1; i<=row; i++)
for(j=1; j<=col; j++)
if(Map[i][j]=='X')
{
xru=j;
yru=i;
}
for(i=1; i<=row; i++)
for(j=1; j<=col; j++)
if(Map[i][j]=='O')
{
xchu=j;
ychu=i;
}
bfs();
}
return 0;
}
void bfs()
{
int i, j;
vis[xru][yru]=1;
point node, t;
queue<point> q;
node.x=xru;
node.y=yru;
node.step=0;
q.push(node);
while(!q.empty())
{
node=q.front();
q.pop();
for(i=0;i<4;i++)
{
t=node;
t.x+=dirx[i];
t.y+=diry[i];
t.step++;
if(t.x==xchu&&t.y==ychu)
{
//printf("%s", t.step<=time?"happy end\n":"bad end\n");
cout<<t.step;
return;
}
if(t.x<1||t.x>col||t.y<1||t.y>row||Map[t.y][t.x]=='*'||vis[t.y][t.x])
continue;
else
{
vis[t.y][t.x]=1;
q.push(t);
}
}
}
printf("没有最短路径\n");
return;
}