今天我们先和深度优先搜索(Depth First Search)和广度优先搜索(Breadth first search)打一架吧!!!
古人云:知己知彼,百战百胜。要打败DFS,我们要知道这个东西是啥,DFS就是不断是试探,试探这个这个方法行不行,与穷举很相似。从英文上解刨一下,看的Depth,就是深度,看到First,就是第一,Search就不用了说了,找呗。连起来,我们先往深的找,也就是一个方法走到头,发现不行,那我们就找浅(second)一点的呗。就像一个地图,有好多好多路,你肯定是一条路摸到黑,发现怎么就堵了呢,没办法走回去看看那个路口没走过,再去探探。
原来DFS是这样一个东西呐,看来惹不起惹不起,溜了溜了。不对,好像只要岔路不是很多,我们走一会还是能走出去的嘛,看来这个小东西不是那么那么的可怕呀,那我们仔细瞅瞅这DFS的有啥用。
这家伙总是和地图有关系
地图长啥样
地图差不多就长这个样子
1 0 1 0 1 0
1 x 0 1 0 1
0 1 1 1 1 1
0 0 0 0 0 y
DFS长啥样
一般呐DFS长这个样子
bool dfs( 初始位置 )
{
if( x跑到的y的位置 )
开心我终于跑出来了(return true)
for( 各个方向跑一下 )
{
往你跑的方向迈一步的位置
if( 判断一下我探的那个位置可不可以跑 ) 不可以我就回去试下一个方向(continue);
可以走,记录一下原来位置我来过
开心的向着希望前进
}
都跑过了,一个都跑不过去,气(return false)
}
看来DFS不是想象中的那么厉害,走去打一架
NOI / 2.5基本算法之搜索 1792:迷宫
#include<iostream>
#include<cstring>
#define Max 110
using namespace std;
int n; // 地图大小
char Map[Max][Max]; // 存储地图
int ha, la, hb, lb; // 起始位置(ha, la) 终点位置(hb, lb)
int dx[4] = {1, 0, -1, 0}; // 这个是方向数组,不明白的小伙伴可以先去学学
int dy[4] = {0, -1, 0, 1};
int vis[Max][Max]; // 标记这个位置有没有来过
bool dfs( int x, int y )
{
if( x == hb && y == lb )
return true;
for( int i = 0; i <= 3; i++ )
{
int tx = x + dx[i];
int ty = y + dy[i];
if( tx < 0 || tx >= n || ty < 0 || ty >= n || vis[tx][ty] ) continue;
if( Map[tx][ty] == '#' ) continue;
vis[tx][ty] = 1;
if( dfs( tx, ty ) ) return true;
}
return false;
}
int main()
{
int t;
cin >> t;
while( t-- )
{
cin >> n;
for( int i = 0; i < n; i++ )
for( int j = 0; j < n; j++ )
cin >> Map[i][j];
cin >> ha >> la >> hb >> lb;
memset( vis, 0, sizeof(vis) );
vis[ha][la] = 1;
if( Map[ha][la]=='#'|| Map[hb][lb]=='#'){
cout<<"NO"<<endl;
continue;
}
if( dfs( ha, la ) ) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}
看来DFS惹不起,咱们去看看BFS可以不可以让我们拿捏
咱们不能走对付DFS的老路了,这都现代了,我们怎么可以自己去探路呢,我们用超声波探路,如果路堵死了就会收到反馈,没堵死就可以走,哈哈,这样不是同步的探到了所有路呐。不过我们要假设这个地图就一个出口,其他地方都堵死了。
挑重点啦挑重点了,看到同步同步同步了吧,我们一下同时向各个方向出发,各个方向都同时同进度的探,这就是BFS呀!!!
地图咱就不看它长啥样了
还是BFS好看
bool BFS( 初始位置 )
{
while( 没找到指定出口 和 还有一些方向的岔口还没探 )
{
东南西北看一下,就一下
记录可以走的
记录走过的
以每个个可以走的为起点重复上面的工作
}
检查一下找到没
没找到,伤心(return false)
}
#include<iostream>
#include<queue>
using namespace std;
int n, m;
char Map[102][102];
int v[102][102];
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, -1, 0, 1};
struct Node{
int x;
int y;
int step;
};
queue<Node> q; // 利用队列先进先出的特性实现同步
int main()
{
cin >> n >> m;
int sx, sy, ex, ey;
for( int i = 1; i <= n; i++ )
for( int j = 1; j <= m; j++ )
{
cin >> Map[i][j];
if( Map[i][j] == 'S' )
{
sx = i;
sy = j;
}else if( Map[i][j] == 'T' )
{
ex = i;
ey = j;
}
}
Node F; // 第一个起始位置
F.step = 0; // 那么步数 0
F.x = sx;
F.y = sy;
q.push(F);
while( !q.empty() )
{
if( q.front().x == ex && q.front().y == ey ) // 判断是否到达指定位置
{
cout << q.front().step << endl;
break;
}
for( int i = 0; i <= 3; i++ ) // 把每个位置的各个可行方向存进队列
{
int tx = q.front().x + dx[i];
int ty = q.front().y + dy[i];
if( tx < 1 || tx > n || ty < 1 || ty > m || v[tx][ty] ) continue;
if( Map[tx][ty] == '#' ) continue;
Node temp;
temp.x = tx;
temp.y = ty;
temp.step = q.front().step + 1;
q.push(temp);
v[tx][ty] = 1;
}
q.pop(); // 这个位置的各个方向试探完了,出队,下一个或是与自己同步的其他位置,或是同步位置都试探完了,队列后是各个同步点的各个同步点。循环试探。
}
return 0;
}
这个题目多了个要求最短路径,所以多了一个step来记录。因为我们知道BFS是同步的,那第一个找到出口的就是最短路径,嘿哈。