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

 

posted @ 2013-12-04 00:22  XYZ篮球  阅读(1660)  评论(0编辑  收藏  举报