DFS、BFS例题

DFS、BFS例题
这有一间铺满方形瓷砖的长方形客房。 每块瓷砖的颜色是红色或者黑色。 一个人站在一块黑色瓷砖上, 他可以从这块瓷砖移动到相邻(即,上下左右)的四块瓷砖中的一块。 但是他只能移动到黑色瓷砖上,而不能移动到红色瓷砖上。

编写一个程序,通过重复上述动作来计算他可以达到的黑色瓷砖的数量。

Input
输入包含多组数据。 每组数据包含两个正整数W和H; H表示瓷砖的行数,W表示瓷砖的列数。 W和H不超过20。

瓷砖的颜色用字符表示,如下所示。

'.' - 黑色瓷砖
'#' - 红色瓷砖
'@' - 站在黑色瓷砖上的人(每组数据中只有一个)

Output
对于每组数据,你的程序应输出一行,其中包含他可以到达的黑色瓷砖数目。(站着的黑色瓷砖也要包含在内)
Sample Input

6 9
....#.
.....#
......
......
......
......
......
#@...#
.#..#.
11 9
.#.........
.#.#######.
.#.#.....#.
.#.#.###.#.
.#.#..@#.#.
.#.#####.#.
.#.......#.
.#########.
...........
11 6
..#..#..#..
..#..#..#..
..#..#..###
..#..#..#@.
..#..#..#..
..#..#..#..
7 7
..#.#..
..#.#..
###.###
...@...
###.###
..#.#..
..#.#..
0 0

Sample Output

45
59
6
13

思路:题目简单的说就是统计从@出发可以达到的最多“.”,可采用DFS深度优先搜索算法,或者BFS

方法一:DFS

从图中某顶点v出发(所以先找出@位置):
(1)访问顶点v(统计ans++并且标记数组e);
(2)依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问,返回上一节点;
(3)若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止

AC代码:

#include<cstdio>
#include<queue>
#include<string.h>
using namespace std;
const int N = 21;
int n, m, sx, sy;
int ans;
char s[N][N];
int e[N][N];
int q[4][2] = { {1,0},{-1,0},{0,1},{0,-1} };
bool jg(int x, int y){
	if (x<1 || x>n || y<1 || y>m)
		return false;
	if (s[x][y] == '#')
		return false;
	if (e[x][y])
		return false;
	return true;
}
void dfs(int x, int y)
{
	if(jg(x,y))
	{
		e[x][y] = 1;
		ans++;
		for (int i = 0; i < 4; i++)
		{
			int nx = x + q[i][0];
			int ny = y + q[i][1];
			dfs(nx, ny);
		}
	}
	else
		return;
}
int main()
{
	int x, y;
	while (scanf("%d %d", &m, &n), m + n)
	{
		memset(e, 0, sizeof e);
		for (int i = 1; i <= n; i++)
			scanf("%s", s[i] + 1);
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= m; j++)
			{
				if (s[i][j] == '@')
				{
					x = i;
					y = j;
				}
			}
		}
		ans = 0;
		dfs(x, y);
		printf("%d\n", ans);
	}
	return 0;
}

方法二:BFS

与DFS同理,不过是将可访问的子节点都会被加进一个先进先出的队列中,而DFS是放入堆栈中,整个过程可以想象成一个倒立的树形
AC代码:

#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
int n, m, sx, sy;
const int N = 21;
char s[N][N];
int e[N][N];
int qwe[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};//上下左右
bool jg(int x, int y)//判断是否能走
{
	if (x<1 || x>n || y<1 || y>m)//超出边界
		return false;
	if (s[x][y] == '#')//为#
		return false;
	if (e[x][y] == 1)//走过了
		return false;
	return true;
}
void bfs()
{
	memset(e, 0, sizeof e);//初始化
	queue<pair<int, int> > que;
	que.push(pair<int, int>(sx, sy));
	e[sx][sy] = 1;//标记找到的位子
	int sum = 0;
	while (!que.empty())//当前位子的上下左右能否走 ,empty判断队列是否为空
	{
		pair<int, int> u = que.front();
		que.pop();
		sum++;
		for (int i = 0; i < 4; i++)
		{
			int nx = u.first + qwe[i][0];
			int ny = u.second + qwe[i][1];
			if (jg(nx, ny))
			{
				e[nx][ny] = 1;
				que.push(pair<int, int>(nx, ny));
			}
		}
	}
	printf("%d\n", sum);
}
int main()
{
	while (scanf("%d %d", &m, &n), m + n)
	{
		for (int i = 1; i <= n; i++)
			scanf("%s", s[i] + 1);
		for (int i = 1; i <= n; i++)//找当前位子
		{
			for (int j = 1; j <= m; j++)
			{
				if (s[i][j] == '@')
				{
					sx = i;
					sy = j;
				}
			}
		}
		bfs();
	}
	return 0;
}

下面是BFSDFS算法的C++模板: BFS算法模板: ```cpp #include <iostream> #include <queue> using namespace std; void BFS(int start, int end) { queue<int> q; bool visited[n]; // 标记节点是否被访问过 int level[n]; // 记录节点的层级 // 初始化visited和level数组 for (int i = 0; i < n; i++) { visited[i = false; level[i = 0; } q.push(start); visited[start = true; while (!q.empty()) { int current = q.front(); q.pop(); // 进行当前节点的操作 for (int neighbor : 获取当前节点的所有邻居节点) { if (!visited = true; level = level[current + 1; } } } // 输出结果,例如输出最短路径的长度 cout << "最短路径长度为:" << level[end << endl; } ``` DFS算法模板: ```cpp #include <iostream> using namespace std; void DFS(int current, bool visited[]) { // 进行当前节点的操作 visited[current = true; // 标记当前节点已访问 for (int neighbor : 获取当前节点的所有邻居节点) { if (!visited = false; } DFS(start, visited); return 0; } ``` 这些模板可以用于解决各种问题,如迷宫、八皇后、n皇后、油田、连通块、数独等。在使用时,根据具体问题的要求选择适合的算法,并按照注释部分进行相应的操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [DFSBFS理解+模板+例题](https://blog.csdn.net/weixin_43876357/article/details/112552683)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值