算法入门经典第六章 例题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找连通块。

posted @ 2017-08-24 14:41  于繁华求淡然  阅读(363)  评论(0编辑  收藏  举报