深度优先搜索dfs和广度优先搜索例题bfs

例1

cpp 复制代码
#include<iostream>
#include<vector>
using namespace std;
int n, m;
vector< vector<char>>grid;
int dx[8] = { -1,-1,-1,0,0,1,1,1 };
int dy[8] = { -1,0,1,-1,1,-1,0,1 };
int ans = 0;
void dfs(int x, int y)
{
	grid[x][y] = '.';
	for (int i = 0; i < 8; i++)
	{
		int nx = x + dx[i];
		int ny = y + dy[i];
		if (nx >= 0 && nx < n && ny >= 0 && ny < m && grid[nx][ny] == 'W')
		{
			dfs(nx, ny);
		}
	}
}
int main()
{
	cin >> n >> m;
	grid.resize(n, vector<char>(m));
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			cin >> grid[i][j];
		}
	}
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			if (grid[i][j] == 'W')
			{
				dfs(i, j);
				ans++;
			}
		}
	}
	cout << ans;
	return 0;
}

解析:

大致思路就是先最开始遍历二维数组(矩形),定义ans记录答案,找到第一个W时,用搜索(广搜或者深搜),将这个W周围所有能到达的W标记为'.',ans++;此时这个W周围所有的湖泊W都被填平了,继续循环,找到第二个W,此时这个W一定和之前那个W是不同的湖泊,因为第一个W周围的湖泊已经被填平了,以此类推,填平第二个W周围湖泊,ans++;

最后输出ans;

  1. 遍历整个二维数组(田地)

  2. 找到第一个 W(水)

  3. 用搜索(DFS/BFS) 把这个 W 连通的所有 W 都标记为 .(相当于"填平"这个水塘)

  4. ans++(发现一个完整的水塘)

  5. 继续遍历 ,因为之前的 W 都被填平了,所以新找到的 W 一定是另一个水塘的

  6. 重复步骤3-5,直到遍历完整个田地

  7. 输出 ans

  • 你有一个有很多水坑的地面

  • 看到一个水坑(第一个 W

  • 用一桶水把这个水坑和所有相连的小水坑都填平(标记为 .

  • 数:啊,这是一个水塘

  • 往前走,又看到一个水坑(肯定和之前那个不相连,不然已经被填平了)

  • 再填平,再计数

  • 最后数出一共有多少个独立的水塘

例2:

cpp 复制代码
#include<iostream>
#include<vector>
using namespace std;
int n, m, t;
int sx, sy, fx, fy;
int dx[4] = { -1,0,0,1 };
int dy[4] = { 0,-1,1,0 };
vector<vector<bool>>visited;
vector<vector<int>>maze;
int ans = 0;
void dfs(int x, int y)
{
	if (x == fx && y == fy)
	{
		ans++;
		return;
	}
	for (int i = 0; i < 4; i++)
	{
		int nx = x + dx[i];
		int ny = y + dy[i];
		if (nx >= 0 && nx < n && ny >= 0 && ny < m && !visited[nx][ny])
		{
			visited[nx][ny] = true;
			dfs(nx, ny);
			visited[nx][ny] = false;
		}
	}
}
int main()
{
	cin >> n >> m >> t;
	cin >> sx >> sy >> fx >> fy;
	sx--; sy--; fx--; fy--;
	visited.resize(n, vector<bool>(m, false));
	maze.resize(n, vector<int>(m));
	for (int i = 0; i < t; i++)
	{
		int x, y;
		cin >> x >> y;
		x--; y--;
		visited[x][y] = true;
	}
	visited[sx][sy] = true;
	dfs(sx, sy);
	cout << ans;
	return 0;
}

解析:

深度优先搜索,从起点开始搜索,起点开始的四个方向,先走一个方向,这个方向再继续向下走,走过的记得标记visited=true,表示已经走过,这次这个路径不会再次走这条路,避免重复,走完之后或者走不通时记得退出来,标记false;

要注意的是这个索引是从1开始的,要是用0开始要给初始值全部减减;

例3:

cpp 复制代码
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
struct point {
    int x, y;
};
int main() {
    int n, m, x0, y0, ans[402][402];
    int dx[8] = { -1, -2, -2, -1, 1, 2, 2, 1 };
    int dy[8] = { -2, -1, 1, 2, -2, -1, 1, 2 };
    queue<point> q;
    memset(ans, -1, sizeof(ans));
    cin >> n >> m >> x0 >> y0;
    ans[x0][y0] = 0;
    point tp = { x0, y0 }, p;
    q.push(tp);
    while (!q.empty()) {
        tp = q.front();
        q.pop();
        for (int i = 0; i < 8; i++) {
            int x = dx[i] + tp.x, y = dy[i] + tp.y;
            if (x < 1 || x > n || y < 1 || y > m || ans[x][y] != -1)
                continue;
            ans[x][y] = ans[tp.x][tp.y] + 1;
            p = { x, y };
            q.push(p);
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cout << ans[i][j] << " ";
        }
        cout << endl;
    }
    return 0;
}
cpp 复制代码
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
int n, m, x, y;
int dx[8] = { -2,-2,2,2,-1,-1,1,1 };
int dy[8] = { -1,1,-1,1,-2,2,-2,2 };
int main()
{
	cin >> n >> m >> x >> y;
	x--; y--;
	vector<vector<int>>arr(n, vector<int>(m, -1));
	vector<vector<bool>>visited(n, vector<bool>(m, false));
	queue<pair<int, int>>q;
	visited[x][y] = true;
	arr[x][y] = 0;
	q.push({ x,y });
	while (!q.empty())
	{
		int x = q.front().first;
		int y = q.front().second;
		q.pop();
		for (int i = 0; i < 8; i++)
		{
			int nx = x + dx[i];
			int ny = y + dy[i];
			if (nx >= 0 && nx < n && ny >= 0 && ny < m && !visited[nx][ny])
			{
				arr[nx][ny] = arr[x][y] + 1;
				q.push({ nx,ny });
				visited[nx][ny] = true;
			}
		}
	}
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			cout << arr[i][j] << " ";
		}
		cout << endl;
	}
	return 0;
}

解析:

广度优先搜索,求最短路径这种用广度优先搜索,本题从x,y开始,广度搜索区别于深度的就是,广度是像水波一样,不断往外蔓延,先走这一圈,这个点能到达的所有点,储存在队列中,然后等把这个点能到达的所有点经历完之后,开始走这个点周围的点,也就是队列里面储存的,所以还要记得走完这个点要删除

相关推荐
寻寻觅觅☆5 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
偷吃的耗子5 小时前
【CNN算法理解】:三、AlexNet 训练模块(附代码)
深度学习·算法·cnn
化学在逃硬闯CS6 小时前
Leetcode1382. 将二叉搜索树变平衡
数据结构·算法
ceclar1236 小时前
C++使用format
开发语言·c++·算法
Gofarlic_OMS7 小时前
科学计算领域MATLAB许可证管理工具对比推荐
运维·开发语言·算法·matlab·自动化
夏鹏今天学习了吗7 小时前
【LeetCode热题100(100/100)】数据流的中位数
算法·leetcode·职场和发展
忙什么果8 小时前
上位机、下位机、FPGA、算法放在哪层合适?
算法·fpga开发
董董灿是个攻城狮8 小时前
AI 视觉连载4:YUV 的图像表示
算法
ArturiaZ9 小时前
【day24】
c++·算法·图论
大江东去浪淘尽千古风流人物9 小时前
【SLAM】Hydra-Foundations 层次化空间感知:机器人如何像人类一样理解3D环境
深度学习·算法·3d·机器人·概率论·slam