zoukankan      html  css  js  c++  java
  • 黑白图像(DFS)

    输入一个n*n的黑白图像(1表示黑色,0表示白色),任务是统计其中八连块的个数。如果两个黑格子有公共边或者公共顶点,就说它们属于同一个八连块。如图6-11所示的图形有3个八连块。

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    图6-11  拥有3个八连块的黑白图形

    【分析】

    用递归求解:从每个黑格子出发,递归访问它所有的相邻黑格。

    int mat[MAXN][MAXN], vis[MAXN][MAXN];
    void dfs(int x, int y) {
      if(!mat[x][y] || vis[x][y])   return;     // 曾经访问过这个格子,或者当前格子是白色
      vis[x][y] = 1;                          // 标记(x,y)已访问过
      dfs(x-1,y-1); dfs(x-1,y); dfs(x-1,y+1);
      dfs(x-1,y);               dfs(x,y+1);
      dfs(x+1,y-1); dfs(x+1,y); dfs(x+1,y+1); // 递归访问周围的八个格子
    }
    这里,黑格(x,y)的mat[x][y]为1,白格为0。为了避免同一个格子访问多次,用标志vis[x][y]记录格子(x,y)是否访问过。在输入之前,在迷宫的外面加上一圈虚拟的白格子,见下面的程序。
    memset(mat, 0, sizeof(mat)); //所有格子都初始化为白色,包括周围一圈的虚拟格子
    memset(vis, 0, sizeof(vis));  // 所有格子都没有访问过
    scanf("%d", &n);
    for(int i = 0; i < n; i++) {
        scanf("%s", s);
        for(int j = 0; j < n; j++)
          mat[i+1][j+1] = s[j]-'0'; // 把图像往中间移动一点,空出一圈白格子
    }
    


     

    接下来,只需不断找黑格,然后调用dfs。从它出发寻找八连块:

    int count = 0;
    for(int i = 1; i <= n; i++)
       for(int j = 1; j <= n; j++)
         if(!vis[i][j] && mat[i][j]) { count++; dfs(i,j); } 
    //找到没有访问过的黑格
    printf("%d
    ", count);
    


     

    完整的程序如下:

    #include <stdio.h>
    #include <string.h>
    const int MAXN = 1000;
    int n;
    
    int mat[MAXN][MAXN], vis[MAXN][MAXN];
    void dfs(int x, int y) {
       
      if(!mat[x][y] || vis[x][y])   return; //曾经访问过这个格子,或者当前
    格子是白色
    vis[x][y] = 1;                        // 标记(x,y)已访问过
      dfs(x-1,y-1); dfs(x-1,y); dfs(x-1,y+1);
      dfs(x-1,y);               dfs(x,y+1);
      dfs(x+1,y-1); dfs(x+1,y); dfs(x+1,y+1); // 递归访问周围的八个格子
    }
    
    int main() {
      char s[MAXN + 10];
      memset(mat, 0, sizeof(mat));  // 所有格子都初始化为白色,包括周围
    一圈的虚拟格子
      memset(vis, 0, sizeof(vis));  // 所有格子都没有访问过
      scanf("%d", &n);
      for(int i = 0; i < n; i++) {
        scanf("%s", s);
        for(int j = 0; j < n; j++)
          mat[i+1][j+1] = s[j]-'0'; // 把图像往中间移动一点,空出一圈白格子
      }
      int count = 0;
      for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
          // 找到没有访问过的黑格
          if(!vis[i][j] && mat[i][j]) { count++; dfs(i,j); } 
      printf("%d
    ", count);
      return 0;
    }
    


     

    上面的函数dfs就是深度优先遍历(Depth-FirstSearch,DFS)的算法,DFS和BFS一样,都是从一个结点出发,按照某种特定的次序访问图中的其他特点。不同的是,BFS使用队列来存放待扩展结点,而DFS使用的是栈。

    附:我自己理解后敲的代码:

    #include <stdio.h>
    #include <string.h>
    #include<algorithm>
    #include<iostream>
    #define M  1020
    using namespace std;
    int n;
    int i,j;
    char map[M][M];
    void dfs(int x,int y)
    {
    
        if(map[x][y]!='1'||x<0||y<0||x>=n||y>=n)
            return; //曾经访问过这个格子,或者当前格子是白色
        else
        {
            map[x][y] = '0';                        // 标记(x,y)已访问过
            dfs(x-1,y-1);
            dfs(x-1,y+1);
            dfs(x-1,y);
            dfs(x,y+1);
            dfs(x,y-1);
            dfs(x+1,y-1);
            dfs(x+1,y);
            dfs(x+1,y+1); // 递归访问周围的八个格子
        }
    }
    
    int main()
    {
        memset(map, 0, sizeof(map));  // 所有格子都没有访问过
        scanf("%d", &n);
        for(i=0; i<n; i++)
            for(j=0; j<n; j++)
                cin>>map[i][j];
    
        int count = 0;
        for(i = 0; i <n; i++)
            for(j = 0; j <n; j++)
            {
                // 找到没有访问过的黑格
                if(map[i][j]=='1')
                {
                    dfs(i,j);
                    count++;
                }
            }
        printf("%d
    ", count);
        return 0;
    }
    /*
    6
    100100
    001010
    000000
    110000
    111000
    010100
    */
    


     

  • 相关阅读:
    redhat 6安装详解
    使用pidstat查看进程资源使用情况
    (转)调优 DB2 UDB v8.1 及其数据库的最佳实践
    (转)LVS安装使用详解
    (转)[小工具] Linux下列格式化工具
    (转)zabbix3.4使用percona-monitoring-plugins监控mysql
    (转)zabbix之生产案例
    (转)CentOS7 LVM添加硬盘及扩容
    (转)计算机网络基础知识总结
    (转)网络基础之网络协议篇
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3226233.html
Copyright © 2011-2022 走看看