洛谷试题 -Lake Counting S
洛谷试题 -Lake Counting S
https://www.luogu.com.cn/problem/P1596
这是一道经典的搜索题,其实就是求其中连通块的数目。
既可以用深搜,又能用广搜。
下面放广搜代码。
#include <iostream>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
int fx[8] = { 0,0,1,1,-1,-1,1,-1 };
int fy[8] = { 1,-1,1,-1,1,-1,0,0 };//8个方向
int total = 0;
char gr[1000][1000];//输入.和w
int vis[1000][1000], n, m;//vis是判断有没有走过
struct MS
{
int x;
int y;
}T1,T2;//结构体 储存点的位置
queue<MS>q;//广搜之必备队列
void bfs(int x1, int y1)
{
T1.x = x1, T1.y = y1;
q.push(T1);
while (!q.empty())
{
T2 = q.front();
q.pop();
for (int i = 0; i < 8; i++)
{
if (!vis[T2.x + fx[i]][T2.y + fy[i]] && gr[T2.x + fx[i]][T2.y + fy[i]] == 'W')//如果点没有走过并且点为‘W’,我们就可以把他放入队列并且标记已经走过
{
T1.x = T2.x + fx[i], T1.y = T2.y + fy[i];
vis[T2.x + fx[i]][T2.y + fy[i]] = 1;
q.push(T1);
}
}
}
}
int main()
{
memset(vis, 0, sizeof(vis));//将vis初始化为0;
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cin >> gr[i][j];
}
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
if (!vis[i][j] && gr[i][j] == 'W')//如果点(i,j)没有走过并且点(i,j)=='w',我们就标记点(i,j)为1,然后广搜,连通块的数目+1;
{
vis[i][j] = 1;
bfs(i, j);
total++;
}
}
}
cout << total;//输出连通块的数目
return 0;
}
下面是深搜代码
#include<iostream>
#include<cstring>
using namespace std;
char GR[1000][1000];
bool vis[1000][1000];
int n, m;
int total = 0;
int fx[8] = { 0,0,1,-1,1,1,-1,-1 };
int fy[8] = { 1,-1,0,0,1,-1,1,-1 };//跟广搜一样,需要八个方向
void dfs(int x,int y)
{
for (int i = 0; i < 8; i++)
{
if (!vis[x + fx[i]][y + fy[i]]&& GR[x + fx[i]][y + fy[i]]=='W')//如果点没有走过并且点为'w',我们就标记点为1,表示已经走过,然后搜索与这个点相邻并且没有标记且为w的点。
{
vis[x + fx[i]][y + fy[i]] = 1;
dfs(x + fx[i], y + fy[i]);
}
}
}
int main()
{
memset(vis, 0, sizeof(vis));
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cin >> GR[i][j];
}
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
if (GR[i][j] == 'W'&&!vis[i][j])//与广搜同理
{
vis[i][j] = 1;
dfs(i, j);
total++;
}
}
}
cout << total;
}