2019_GDUT_新生专题I选集DFS/BFS解连通块问题
题目链接:
http://poj.org/problem?id=2386题意:由于最近的降雨,在农夫约翰田地的不同地方积聚了水,用N x M(1 <= N <= 100; 1 <= M <= 100)正方形的矩形表示。 每个方格包含水(‘W’)或旱地(’。’)。 农夫约翰想弄清楚他的田地里形成了多少个池塘。 池塘是一组相连的正方形,里面有水,其中一个正方形被认为与八个池塘相邻。给定农夫约翰的田野图,确定他有多少个池塘。
搜索里面经典的连通块问题,思路是比较简单的,在找到某个地方有积水后,从这一格开始往八个不同的方向找有没有积水。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int map[1005][1005];
int ax[8]={-1,0,1,-1,1,-1,0,1};
int ay[8]={-1,-1,-1,0,0,1,1,1};
void dfs(int x,int y){
if (!map[x][y]) return;
map[x][y]=0;
for (int i=0;i<8;i++)
dfs(x+ax[i],y+ay[i]);//遍历积水附近的八个格子
return;
}
int main(){
int n,m;
scanf("%d %d",&n,&m);
char c;
getchar();
for (int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++)
{
c=getchar();
if (c=='W') map[i][j]=1;
else map[i][j]=0;
}
getchar();
}
int ans=0;//ans记录找到的池塘数
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (map[i][j])
{
ans++;
dfs(i,j);
}
printf("%d\n",ans);
return 0;
}
题目链接:http://poj.org/problem?id=1979
题意:有一个长方形的房间,覆盖着正方形的瓷砖。 每个图块都用红色或黑色着色。 一个人站在黑色的瓷砖上。 他可以从一个图块移动到四个相邻图块之一。 但是他不能在红色瓷砖上移动,只能在黑色瓷砖上移动。
编写一个程序,通过重复上述动作来计算他可以到达的黑色瓷砖的数量。
与前面那题类似,只是联通的规则由八向变成四向,而且只需要求特定的联通块的大小,那么只需要在读入的时候记录起点然后dfs就可。
另外是多组数据输入,记得每次初始化好就行。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int map[1005][1005],ans=0;
int ax[4]={-1,0,1,0};
int ay[4]={0,-1,0,1};
void dfs(int x,int y){
if (!map[x][y]) return;
map[x][y]=0;
ans++;
for (int i=0;i<=3;i++)
dfs(x+ax[i],y+ay[i]);
return;
}
int main(){
int n,m,x,y;
scanf("%d %d",&n,&m);
while (n||m){
char c;
getchar();
for (int i=1;i<=m;i++)
{
for (int j=1;j<=n;j++)
{
c=getchar();
if (c=='#') map[i][j]=0;
else map[i][j]=1;
if (c=='@')
{
x=i;
y=j;
}//记录起点位置
}
getchar();//清楚缓冲区的换行符
}
ans=0;//ans用于记录目标连通块大小
for (int i=1;i<=m;i++) map[i][n+1]=0;
for (int i=1;i<=n;i++) map[m+1][i]=0;//设置边界
dfs(x,y);
printf("%d\n",ans);
scanf("%d %d",&n,&m);
}
return 0;
}
来源:CSDN
作者:TouhouLZFeng
链接:https://blog.csdn.net/TouhouLZFeng/article/details/103958216