搜索
- 深度优先搜索
- 广度优先搜索
这两个搜索算法是最基本的暴力技术
- 一只老鼠走迷宫。它们在每个路口都向一个方向走 ,如果碰壁 那么就退回一步 走原来相反的方向 这个算法就是 深度优先算法(DFS)
- 一群老鼠走迷宫 ,假设老鼠的数量是无限的 一个路口放部分老鼠 一只老鼠走碰壁 那么就停下来 如果老鼠到达的路口是其他老鼠来过的 也停下来 这个就是广度优先搜索(BFS)
BFS
我们稍微的探讨一下
BFS可以理解成分子的扩散
在一个上下左右都可以走的地方 一个分子向四个方向发出分身 自身死亡
也便是自己这个地方标记成路障 避免重复路过
这个算法 会先在最近的地方扩散
自身需要标记成路障的特性 我们可以理解为是队列
队列:先进先出表
标记初始起点1
进过上下左右的遍历 如果是可以走的地方
我们就扩散 并标记 再让队首 就是本身这个元素删除
其余元素有序的进行扩散
在算法的理解上 这个本身是并行的 但是我们的计算机没有办法做到 我的知识面还是没有办法做到
因此我们只能模拟出并行的算法
Red and Black
又一个矩形房间 瓷砖分别是红色 黑色。
一个人站在房间的某一个地方。
他可以上下左右的走
但是只能在黑色的地方走
我们要计算他可以在黑色的瓷砖上走多少步
用户输入:房间的长宽 已经房间的黑色 红色瓷砖
我们用 ‘#’表示红色瓷砖 也就是上面说的路障
用’.’ 表示黑色瓷砖
稍微模拟一下
- 1进队 队列是所有元素是1
- 1出队 并且在出队前记录他的位置 然后判断他的可行方向 遍历进队
- 根据有序的标记 扩散
- 不断的删除队首
- 最后的队列一定是空的
- 然后利用num记录可以走的黑色瓷砖数
利用STL
queue这个函数可以建立一个队列
利用bits/stdc++.h这个头文件 包含了所有c++头文件
queue q;
这个是函数的使用方法
方向遍历
int dir[4][2]={
{-1,0},
{0,-1},
{1,0},
{0,1}
};
这个数组分别表示了左 上 右 下
结构体变量 stu.h+dir[i][1] stu.l+dir[i][0]
我写贪吃蛇的地方用了遍历方向的方法是if
但是十分繁琐 并且这个不需要我输入
所以只需要自己遍历就好了
那么二维数组的遍历方向这个是比较简单的
BFS算法
#include <bits/stdc++>
using namespace std;
char room[23][23]; //限制23*23
int dir[4][2]={
{-1,0},
{0,-1},
{1,0},
{0,1}
};
int HANG,LIE,num;
#define CHECK(h,l)(h<HANG&&h>=0&&l<LIE&&l>=0)
struct node{
int h;
int l;
};//记录room的位置
void BFS(int H,int L){
num=1;
queue<int>q;
node start,next;
start.h=H;
start.l=L;
q.push(start); // 队列放入第一个数据
while(!q.empty()){
start=q.front();//记录队首
q.pop();//队首删除
for(int i=0;i<4;i++)//遍历四个方向
{
next.h=start.h+dir[i][1];
next.l=start.l+dir[i][0];
//遍历四个方向
if(CHECK(next.h,next.l)&&room[next.h][next.l]=='.'){
//CHECK判断有没有出界
room[next.h][next.l]='#';
//处理标记过的元素 就是自身标记黑色 避免重复
num++;
q.push(next); //如果下一个路可以走 就放入队列
}
}
}
}
int main(){
int H;
int L;
cin>>H;
cin>>L;
for(int i=0;i<HANG;i++)
for(int j=0;j<LIE;j++){
cin>>room[i][j];
if(room[i][j]=='@'){
H=i;
L=j;
}
}
num=0;
BFS(H,L);
cout<<num<<endl;
return 0;
}
BFS解决这问题就可以很明白的理解到扩散的情景
结尾
开学 快乐