概述
BFS英文全称是Breadth First Search。
广度优先搜索使用队列(queue)来实现,整个过程也可以看做一个倒立的树形:
1、把根节点放到队列的末尾。
2、每次从队列的头部取出一个元素,查看这个元素所有的下一级元素,把它们放到队列的末尾。并把这个元素记为它下一级元素的前驱。
3、找到所要找的元素时结束程序。
4、如果遍历整个树还没有找到,结束程序。
队列使用详见:STL内置函数用法详解——五、queue(提示:可在博客内容的右侧菜单栏中找到目录方便快速查找)
BFS()
{
初始化队列
while(队列不为空且未找到目标节点)
{
取队首节点扩展,并将扩展出的非重复节点放入队尾;
必要时记住每个节点的父节点;
}
}
void bfs(起始点)
{
将起始点放入队列中;
标记起点已访问;
while(队列不为空)
{
访问队列中首元素x;
删除队首元素;
for(x所有相邻点)
{
if(该点未被访问过且合法)
将该点加入队列末尾;
}
}
队列为空,广搜结束;
}
一、抓住这头牛
题目描述:
农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0<=N<=100000),牛位于点K(0<=K<=100000)。农夫有两种移动方式:
1、从X移动到X-1或X+1,每次移动花费一分钟
2、从X移动到2*X,每次移动花费一分钟
假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?
输入:
农夫的起始位置N,为牛的位置K
代码如下:
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int N,K; //N为农夫的起始位置,K为牛的位置
const int MAXN=100000;
int visited[MAXN+10];
struct Step{
int x; //位置
int steps; //到达x所需步数
Step(int xx,int s):x(xx),steps(s){}
/*
Step(int xx,int s):x(xx),steps(s){} 为Step结构体的构造函数
等价于
Step(int xx,int s)
{
x=xx;
steps=s;
}
*/
};
queue<Step> q; //队列,即Open表
int main()
{
cin>>N>>K;
memset(visited,0,sizeof(visited));
q.push(Step(N,0));
visited[N]=1;
while(!q.empty())
{
Step s=q.front();
if(s.x==K) //找到目标
{
cout<<s.steps<<endl;
return 0;
}
else
{
if(s.x-1>=0&&!visited[s.x-1])
{
q.push(Step(s.x-1,s.steps+1));
visited[s.x-1]=1;
}
if(s.x+1<=MAXN&&!visited[s.x+1])
{
q.push(Step(s.x+1,s.steps+1));
visited[s.x+1]=1;
}
if(s.x*2<=MAXN&&!visited[s.x*2])
{
q.push(Step(s.x*2,s.steps+1));
visited[s.x*2]=1;
}
q.pop();
}
}
return 0;
}
补充说明 结构体中使用构造函数初始化 :
构造函数:
struct Student{
string name;
int score;
Student(string n,int s)
{
name=n;
score=s;
}
};
语法上,构造函数具有以下性质:
1、函数体名与结构体名完全相同
2、不能定义返回值类型,也不能有return语句
3、可以有形参,也可以没有,可以带默认参数
4、可以重载默认构造函数:
struct Student{
string name;
int score;
Student() {}
};
注意:同一个结构体中,不能出现两个默认构造函数。初始化列表:
struct Student{
string name;
int score;
Student() {} //注意不可省略默认构造函数
Student(string n,int s):name(n),score(s) {}
};
二、迷宫
第十届蓝桥杯 试题E:迷宫 —— C++ 超详解
三、密码锁
题目描述:
现在一个紧急的任务是打开一个密码锁。 密码由四位数字组成,每个数字从1到9进行编码。每次可以对任何一位数字加1或减1。当将9加1时,数字将变为1,当将1减1时,数字将变为9.你也可以交换相邻数字,每一个行动记作异步。现在你的任务是使用最小的步骤来打开锁。注意:最左边的数字不与最右边的数字相邻。
输入:
第一行输入四个数字,表示密码锁的初始状态。
第二行输入四个数字,表示开锁的密码。
输出:
最小步数:
代码如下:
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;
struct node{
int num[4],step;
}first,last;
int vis[11][11][11][11];
void bfs()
{
int i;
node a,next;
queue<node> q;
a=first;
a.step=0;
q.push(a);
memset(vis,0,sizeof(vis));
vis[a.num[0]][a.num[1]][a.num[2]][a.num[3]]=1;
while(!q.empty())
{
a=q.front();
q.pop();
if(a.num[0]==last.num[0]&&a.num[1]==last.num[1]&&a.num[2]==last.num[2]&&a.num[3]==last.num[3])
{
printf("%dn",a.step);
return;
}
for(i=0;i<4;++i) //+1
{
next=a;
++next.num[i];
if(next.num[i]==10)
next.num[i]=1;
if(!vis[next.num[0]][next.num[1]][next.num[2]][next.num[3]])
{
vis[next.num[0]][next.num[1]][next.num[2]][next.num[3]]=1;
++next.step;
q.push(next);
}
}
for(i=0;i<4;++i) //-1
{
next=a;
--next.num[i];
if(next.num[i]==0)
next.num[i]=9;
if(!vis[next.num[0]][next.num[1]][next.num[2]][next.num[3]])
{
vis[next.num[0]][next.num[1]][next.num[2]][next.num[3]]=1;
++next.step;
q.push(next);
}
}
for(i=0;i<3;++i) //交换
{
next=a;
next.num[i]=a.num[i+1];
next.num[i+1]=a.num[i];
if(!vis[next.num[0]][next.num[1]][next.num[2]][next.num[3]])
{
vis[next.num[0]][next.num[1]][next.num[2]][next.num[3]]=1;
++next.step;
q.push(next);
}
}
}
}
int main()
{
int i,j;
for(i=0;i<4;++i)
scanf("%d",&first.num[i]);
for(i=0;i<4;++i)
scanf("%d",&last.num[i]);
bfs();
return 0;
}
运行结果:
最后
以上就是怕黑薯片为你收集整理的BFS入门这一篇就够了——C++一、抓住这头牛二、迷宫三、密码锁的全部内容,希望文章能够帮你解决BFS入门这一篇就够了——C++一、抓住这头牛二、迷宫三、密码锁所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复