zoukankan      html  css  js  c++  java
  • floodfill算法解题示例

    Flood fill算法是从一个区域中提取若干个连通的点与其他相邻区域区分开(或分别染成不同颜色)的经典算法。因为其思路类似洪水从一个区域扩散到所有能到达的区域而得名。在GNU Go扫雷中,Flood Fill算法被用来计算需要被清楚的区域。

    算法实现

    最简单的实现方法是采用深度优先搜索的递归方法,也可以采用广度优先搜索的迭代来实现。

    void flood_fill(int x,int y,int color)
    {
      area[x][y]=color;
      if(x>0&&area[x-1][y]==0)flood_fill(x-1,y,color);
      if(y>0&&area[x][y-1]==0)flood_fill(x,y-1,color);
      if(x<MAX_X&&area[x+1][y]==0)flood_fill(x+1,y,color);
      if(y<MAX_Y&&area[x][y+1]==0)flood_fill(x,y+1,color);
     
    }
    ——————维基百科:http://zh.wikipedia.org/wiki/Flood_fill

    1002: 当不成勇者的Water只好去下棋了

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 110  Solved: 47
    [Submit][Status][Web Board]

    Description

    由于魔王BOSS躲起来了,说好要当勇者的Water只好去下棋了,他很厉害,基本每局必输。

    Water总是不知道为什么把自己的棋下得东一块西一块,而块与块之间总是被对手的棋隔开。概率统计挂了的Water一直没搞清楚到底自己被别人分成了多少块,又来找你帮忙。  
    假定Water的棋为X,对手的棋为O。 
    给出一个矩阵棋盘,上面布满了棋子,求Water的棋子究竟被对手分成了多少块?

    (为了和谐,我们还是用0011代表OOXX)

    Input

    第一行为n, m。 (0 < n,m <= 100)
    接下来 n 行 m 列为01矩阵。
    1 为Water的棋。

    Output

    每组数据输出一行,表示块数。

    Sample Input

    2 2
    01
    10
    2 3
    101
    011
    

    Sample Output

    2
    2
    

    HINT

     

    Source

      1 #include<iostream>
      2 using namespace std;
      3 struct Dir {
      4       int x;
      5       int y;
      6 };
      7 struct Node {//节点的结构为:x,y为下标,dir[4]为该节点的四个方向,color用来表示是否已经被访问(不为0)以及在第几个块的,g为该节点在图中的值 
      8        int x;
      9        int y;
     10        Dir dir[4];
     11        int color;
     12        char g;
     13        Node() {
     14            x = 0;
     15            y = 0;
     16            color = 0;
     17            g = ' ';
     18            dir[0].x = x-1;
     19            dir[0].y = y;
     20            dir[1].x = x;
     21            dir[1].y = y+1;
     22            dir[2].x = x+1;
     23            dir[2].y = y;
     24            dir[3].x = x;
     25            dir[3].y = y-1;
     26        }
     27        void setDir(int x_, int y_) {//设置节点的方向 ,刚做题时忘记了,搞得color值不会变化 
     28            dir[0].x = x_-1;
     29            dir[0].y = y_;
     30            dir[1].x = x_;
     31            dir[1].y = y_+1;
     32            dir[2].x = x_+1;
     33            dir[2].y = y_;
     34            dir[3].x = x_;
     35            dir[3].y = y_-1; 
     36        }
     37 };
     38 int color_ = 0;
     39 int m;
     40 int n;
     41 bool ValidNode(Node& node, int m, int n) {//判断一个节点是否有效,在本题中有效的条件是没有越界还有该临近节点(g=1)未被访问过 ,即color=0 ,同时要使用引用才能在该函数内改变该引用变量的值 
     42      if ((node.x >= 0 && node.x < m) && (node.y >=0 && node.y < n)) {
     43          if (node.color == 0 && node.g == '1')
     44              return true;
     45      }
     46      return false;
     47 } 
     48 void initialize(Node (*total)[101]) {//初始化图 
     49      char qi;
     50      for (int i = 0; i < m; i++) {
     51          for (int j = 0; j < n; j++) {
     52              cin >> qi;
     53              total[i][j].x = i;
     54              total[i][j].y = j;
     55              total[i][j].g = qi;
     56              total[i][j].setDir(i, j);//setDir不能忘记了,不然该节点的四个方向不能与下标x,y对应 
     57          }
     58      }
     59 }
     60 void floodfill(Node (*total)[101], Node& node) {//floodfill算法递归访问临近节点,并将color值修改,以表示访问过和记录在第几块,别忘了引用 
     61      node.color = color_;
     62      for (int i = 0; i < 4; i++) {
     63          if (ValidNode(total[node.dir[i].x][node.dir[i].y], m, n))
     64              floodfill(total, total[node.dir[i].x][node.dir[i].y]);
     65      }
     66 }             
     67 int main() {
     68     while (cin >> m >> n) {
     69        Node qipan[101][101];
     70        initialize(qipan);
     71        /*cout << "初始化的图:g+color" << endl; 
     72        for (int i = 0; i < m; i++) {
     73           for (int j = 0; j < n; j++) {
     74               cout << qipan[i][j].g  << qipan[i][j].color << " ";
     75           }
     76           cout << endl;
     77        }*/
     78        for (int i = 0; i < m; i++) {
     79           for (int j = 0; j < n; j++) {
     80               if (ValidNode(qipan[i][j], m, n)) {
     81                   color_++;               
     82                   floodfill(qipan, qipan[i][j]);
     83               }
     84           }
     85        }
     86        /*cout << "分块后的图:g+color" << endl; 
     87        for (int i = 0; i < m; i++) {
     88           for (int j = 0; j < n; j++) {
     89               cout << qipan[i][j].g  << qipan[i][j].color << " ";
     90           }
     91           cout << endl;
     92        }*/
     93        /*cout << "color的值,即分为了多少块:"; */
     94        cout <<  color_ << endl;//此时color值就是图被分成几块 
     95        color_ = 0;//color_这个全局变量要复位为0,以便下一次使用 
     96         
     97     }
     98     return 0;
     99 }
    100  
    101 /**************************************************************
    102     Problem: 1002
    103     User: 12330344
    104     Language: C++
    105     Result: Accepted
    106     Time:584 ms
    107     Memory:1680 kb
    108 ****************************************************************/

    输出结果:4*4为例:

    图遍历算法——DFS、BFS、A*、B*和Flood Fill 遍历算法大串讲:http://dsqiu.iteye.com/blog/1689130

  • 相关阅读:
    alpha冲刺—Day5
    alpha冲刺—Day4
    alpha冲刺—Day3
    alpha冲刺—Day2
    alpha冲刺—Day1
    团队作业第五次—alpha冲刺博客汇总
    团队作业第四次—项目系统设计与数据库设计
    团队作业第三次—项目需求分析
    团队作业第二次—团队Github实战训练
    win10配置java环境变量,解决javac不是内部或外部命令等问题
  • 原文地址:https://www.cnblogs.com/xieyizun-sysu-programmer/p/Floodfill.html
Copyright © 2011-2022 走看看