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 MBSubmit: 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