算法入门经典第六章 例题6-12 油田
例题:输入一个m行n列的字符矩阵,统计字符“@”组成多少个八连块。如果两个字符“@”所在的格子相邻(横、纵或者对角线方向),就说它们属于一个八连块。例如,下图中有两个八连块
输入:
输出:
2
#include<cstdio> #include<cstring> const int maxn=100+5; //存图的数组 char pic[maxn][maxn]; //m 图有几行 n图有几列 idx[i][j]连通分量编号 int m,n,idx[maxn][maxn]; //r 图的纵坐标 c图的横坐标 id连通分量编号 void dfs(int r,int c,int id) { if(r<0||r>=m||c<0||c>=n) return; //出界的格子 if(idx[r][c]>0||pic[r][c]!='@')return; //不是“@”或者已经访问过的格子 idx[r][c]=id; //连通分量编号 //给相邻的格子(横竖或者对角线方向)赋值连通分量编号 for(int dr=-1;dr<=1;dr++) for(int dc=-1;dc<=1;dc++) if(dr!=0||dc!=0) dfs(r+dr,c+dc,id); } int main() { //要想停止输入则将m或者n赋值为0 while(scanf("%d%d",&m,&n)==2&&m&&n) { for(int i=0;i<m;i++) scanf("%s",pic[i]); memset(idx,0,sizeof(idx)); //记录有几个连通分量 int cnt=0; for(int i=0;i<m;i++) for(int j=0;j<n;j++) if(idx[i][j]==0&&pic[i][j]=='@') dfs(i,j,++cnt); printf("%d\n",cnt); } return 0; }
分析:
用DFS实现的基本思路是:从每个“@”格子出发,递归遍历它周围的“@”格子。每次访问一个格子时就给它写上一个“连通分量编号”(即下面代码的idx数组),这样就可以在访问之前检查它是否已经有了编号,从而避免同一个格子访问多次。
图描述的是一些个体之间的关系。与线性表和二叉树不同的是:这些个体之间既不是前驱后继的顺序关系,也不是祖先后代的层次关系,而是错综复杂的网状关系。
和二叉树的遍历类似,图也有DFS和BFS遍历,由于DFS更容易编写,一般用DFS找连通块。