出處:http://acm.nudt.edu.cn/~twcourse/ConnectedComponentLabeling.html
Flood Fill Algorithm
Flood Fill Algorithm 的 flood 是指「淹水」, fill 是指「填滿」。
這個演算法的功用,舉例來說,就像是小畫家倒墨水的功能,將鄰近同顏色的區塊,一併染成同一個顏色。
電腦中的圖片,都是以一點一點的像素所組成的。簡單的來說,一張圖片,可以想做是一張方格紙,每個格子都對應到圖片上的一點像素。 Flood Fill Algorithm會以某一格當做起點,開始向四周淹水,只要鄰近的格子是空的(顏色一樣的),水就會淹過去。
如上圖左邊中間黑點,慢慢往四周圍擴散
這裡提供一個簡單的程式碼。它往上下左右四個方向淹水。
- int picture[11][21];
-
- int flood(int x, int y, int fill_color, int original_color)
- {
- if (x>=0 && x<11 && y>=0 && y<21)
- if (picture[x][y] == original_color)
- {
- picture[x][y] = fill_color;
- flood(x+1, y, fill_color, original_color);
- flood(x-1, y, fill_color, original_color);
- flood(x, y+1, fill_color, original_color);
- flood(x, y-1, fill_color, original_color);
- }
- }
-
- int main()
- {
-
- flood(5, 4, 3, picture[5][4]);
- }
亦可以將淹水的程式碼寫成這種風格:
- const int dx[4] = {1, -1, 0, 0};
- const int dy[4] = {0, 0, 1, -1};
-
- bool on_picture(int x, int y)
- {
- return x>=0 && x<11 && y>=0 && y<21;
- }
-
- void flood(int x, int y, int fill_color, int original_color)
- {
-
- if (!on_picture(x, y)) return;
-
-
- if (picture[x][y] != original_color) return;
-
- picture[x][y] = fill_color;
-
- for (int i=0; i<4; i++)
- {
-
- int next_x = x + dx[i], next_y = y + dy[i];
- flood(next_x, next_y, fill_color, original_color);
- }
- }
實作時要特別注意,避免淹過水的地方又反反覆覆淹了很多次。這會使程式的效率大幅下降,其執行速度之慢,可讓程式在有生之年都不會結束。
言盡於此。這裡有許多類似於 Flood Fill Algorithm的演算法,可以參考:
http://www.codeproject.com/gdi/QuickFill.asp
兩點是否在同一區塊
Flood Fill Algorithm 除了可以達到小畫家中倒墨水的效果之外,還可以找出地圖上某兩點是不是屬於同一區塊。
判斷座標 (5,4) 和座標 (10,10) 是不是屬於同一區塊的方法:
- int picture[11][21];
- bool visit[11][21];
-
- void flood(int x, int y, int original_color)
- {
- if (x>=0 && x<11 && y>=0 && y<21)
- if (picture[x][y] == original_color && !visit[x][y])
- {
- visit[x][y] = true;
- flood(x+1, y, original_color);
- flood(x-1, y, original_color);
- flood(x, y+1, original_color);
- flood(x, y-1, original_color);
- }
- }
-
- int main()
- {
-
- for (int i=0; i<11; i++)
- for (int j=0; j<21; j++)
- visit[i][j] = false;
-
-
- flood(5, 4);
-
- if (visit[10][10])
- cout << "兩點相連" << endl;
- else
- cout << "兩點不相連" << endl;
- }
不同區塊的數目
找出這張圖總共有幾個區塊。只需修改一下 main function :
- int main()
- {
- for (int i=0; i<11; i++)
- for (int j=0; j<21; j++)
- visit[i][j] = false;
-
- int count = 0;
- for (int x=0; x<11; x++)
- for (int y=0; y<21; y++)
- if (!visit[x][y])
- {
- count++;
- flood(x, y, picture[x][y]);
- }
-
- cout << "總共有" << count << "個區塊" << endl;
- }
計算距離
找出由某一點開始,到其他所有點的距離。常用來解決走迷宮之類的問題。
- int picture[11][21];
- int dist[11][21];
-
- void flood(int x, int y, int d, int original_color)
- {
- if (x>=0 && x<11 && y>=0 && y<21)
- if (picture[x][y] == original_color && d < dist[x][y])
- {
- dist[x][y] = d;
- flood(x+1, y, d+1, original_color);
- flood(x-1, y, d+1, original_color);
- flood(x, y+1, d+1, original_color);
- flood(x, y-1, d+1, original_color);
- }
- }
-
- int main()
- {
- for (int i=0; i<11; i++)
- for (int j=0; j<21; j++)
- dist[i][j] = 0;
-
- flood(5, 4, 0, picture[5][4]);
- }
Flood Fill Algorithm 應用廣泛。練習題目也不少。
留言