UVA 572 -- Oil Deposits(DFS求连通块)
图也有DFS和BFS遍历,由于DFS更好写,所以一般用DFS寻找连通块。
下述代码用一个二重循环来找到当前格子的相邻8个格子,也可用常量数组或者写8条DFS调用。
下述算法是:种子填充(floodfill)
两种连通区域
四连通区域:从区域内一点出发,可通过上、下、左、右四个方向的移动组合,在不越出区域的前提下,能到达区域内的任意像素
八连通区域:从区域内每一像素出发,可通过八个方向,即上、下、左、右、左上、右上、左下、右下移动的组合,在不越出区域的前提下,能到达区域内的任意像素。
基本原理
从多边形区域内部的某一像素点(称为种子)开始,由此出发找到区域内的其它所有像素。
采用的边界定义
区域边界上所有像素均具有某个特定的颜色值,区域内部所有像素均不取这一特定颜色,而边界外的像素则可具有与边界相同的颜色值。
算法的执行过程:
从(x,y)开始,先检测该点的颜色,若它与边界色和填充色均不相同,则用填充色填充该点。然后检测相邻位置,以确定它们是否是边界色和填充色,若不是,则填充该相邻点。直到检测完区域边界范围内的所有像素为止。
从当前点检测相邻像素的方法:四连通或八连通
从四个方向寻找下一个像素,称为四向算法(只能填充四连通区域);
从八个方向寻找下一个像素,称为八向算法(可以填充八连通区域和四连通区域)。
四连通区域的种子填充递归算法:
1 void ZhongZiTC4 (int seedx, int seedy, int fcolor, int bcolor) 2 { 3 int current = getpixel (seedx, seedy); 4 if ((current != bcolor) && (current != fcolor)) 5 { putpixel (seedx, seedy, fcolor); 6 ZhongZiTC4 (seedx+1, seedy, fcolor, bcolor); //右 7 ZhongZiTC4 (seedx–1, seedy, fcolor, bcolor); //左 8 ZhongZiTC4 (seedx, seedy+1, fcolor, bcolor); //上 9 ZhongZiTC4 (seedx, seedy–1, fcolor, bcolor); //下 10 } 11 }
UVA 572代码:
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 const int maxn = 100+5; 5 char deposits[maxn][maxn]; 6 int id[maxn][maxn]; 7 int rm,cm; 8 void dfs(int r,int c,int cnt) 9 { 10 ///判断是否出界 11 if(r<0 || r>=rm || c<0 || c>=cm) return; 12 ///临界条件 13 if(deposits[r][c] == '*') return; 14 if(id[r][c]) return; 15 16 id[r][c] = cnt; 17 for(int i=-1;i<=1;i++) 18 for(int j=-1;j<=1;j++) 19 if(i!=0 || j!=0) dfs(r+i,c+j,cnt); 20 21 } 22 23 int main() 24 { 25 26 while(cin>>rm>>cm && rm && cm) 27 { 28 for(int i=0;i<rm;i++) cin>>deposits[i]; 29 int cnt=0; 30 memset(id,0,sizeof(id)); 31 for(int i=0;i<rm;i++) 32 for(int j=0;j<cm;j++) 33 { 34 if(!id[i][j] && deposits[i][j]=='@')///没有编号 35 dfs(i,j,++cnt); 36 } 37 cout<<cnt<<endl; 38 39 } 40 return 0; 41 }