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;
}