黑白圖像(DFS)

輸入一個n*n的黑白圖像(1表示黑色,0表示白色),任務是統計其中八連塊的個數。如果兩個黑格子有公共邊或者公共頂點,就說它們屬於同一個八連塊。如圖6-11所示的圖形有3個八連塊。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

圖6-11  擁有3個八連塊的黑白圖形

【分析】

用遞歸求解:從每個黑格子出發,遞歸訪問它所有的相鄰黑格。

int mat[MAXN][MAXN], vis[MAXN][MAXN]; void dfs(int x, int y) {   if(!mat[x][y] || vis[x][y])   return;     // 曾經訪問過這個格子,或者當前格子是白色   vis[x][y] = 1;                          // 標記(x,y)已訪問過   dfs(x-1,y-1); dfs(x-1,y); dfs(x-1,y+1);   dfs(x-1,y);               dfs(x,y+1);   dfs(x+1,y-1); dfs(x+1,y); dfs(x+1,y+1); // 遞歸訪問周圍的八個格子 } 這裏,黑格(x,y)的mat[x][y]爲1,白格爲0。爲了避免同一個格子訪問多次,用標誌vis[x][y]記錄格子(x,y)是否訪問過。在輸入之前,在迷宮的外面加上一圈虛擬的白格子,見下面的程序。 memset(mat, 0, sizeof(mat)); //所有格子都初始化爲白色,包括周圍一圈的虛擬格子 memset(vis, 0, sizeof(vis));  // 所有格子都沒有訪問過 scanf("%d", &n); for(int i = 0; i < n; i++) {     scanf("%s", s);     for(int j = 0; j < n; j++)       mat[i+1][j+1] = s[j]-'0'; // 把圖像往中間移動一點,空出一圈白格子 } 


 

接下來,只需不斷找黑格,然後調用dfs。從它出發尋找八連塊:

int count = 0; for(int i = 1; i <= n; i++)    for(int j = 1; j <= n; j++)      if(!vis[i][j] && mat[i][j]) { count++; dfs(i,j); }  //找到沒有訪問過的黑格 printf("%d\n", count); 


 

完整的程序如下:

#include <stdio.h> #include <string.h> const int MAXN = 1000; int n;  int mat[MAXN][MAXN], vis[MAXN][MAXN]; void dfs(int x, int y) {       if(!mat[x][y] || vis[x][y])   return; //曾經訪問過這個格子,或者當前 格子是白色 vis[x][y] = 1;                        // 標記(x,y)已訪問過   dfs(x-1,y-1); dfs(x-1,y); dfs(x-1,y+1);   dfs(x-1,y);               dfs(x,y+1);   dfs(x+1,y-1); dfs(x+1,y); dfs(x+1,y+1); // 遞歸訪問周圍的八個格子 }  int main() {   char s[MAXN + 10];   memset(mat, 0, sizeof(mat));  // 所有格子都初始化爲白色,包括周圍 一圈的虛擬格子   memset(vis, 0, sizeof(vis));  // 所有格子都沒有訪問過   scanf("%d", &n);   for(int i = 0; i < n; i++) {     scanf("%s", s);     for(int j = 0; j < n; j++)       mat[i+1][j+1] = s[j]-'0'; // 把圖像往中間移動一點,空出一圈白格子   }   int count = 0;   for(int i = 1; i <= n; i++)     for(int j = 1; j <= n; j++)       // 找到沒有訪問過的黑格       if(!vis[i][j] && mat[i][j]) { count++; dfs(i,j); }    printf("%d\n", count);   return 0; } 


 

上面的函數dfs就是深度優先遍歷(Depth-FirstSearch,DFS)的算法,DFS和BFS一樣,都是從一個結點出發,按照某種特定的次序訪問圖中的其他特點。不同的是,BFS使用隊列來存放待擴展結點,而DFS使用的是棧。

 

附:我自己理解後敲的代碼:

#include <stdio.h> #include <string.h> #include<algorithm> #include<iostream> #define M  1020 using namespace std; int n; int i,j; char map[M][M]; void dfs(int x,int y) {      if(map[x][y]!='1'||x<0||y<0||x>=n||y>=n)         return; //曾經訪問過這個格子,或者當前格子是白色     else     {         map[x][y] = '0';                        // 標記(x,y)已訪問過         dfs(x-1,y-1);         dfs(x-1,y+1);         dfs(x-1,y);         dfs(x,y+1);         dfs(x,y-1);         dfs(x+1,y-1);         dfs(x+1,y);         dfs(x+1,y+1); // 遞歸訪問周圍的八個格子     } }  int main() {     memset(map, 0, sizeof(map));  // 所有格子都沒有訪問過     scanf("%d", &n);     for(i=0; i<n; i++)         for(j=0; j<n; j++)             cin>>map[i][j];      int count = 0;     for(i = 0; i <n; i++)         for(j = 0; j <n; j++)         {             // 找到沒有訪問過的黑格             if(map[i][j]=='1')             {                 dfs(i,j);                 count++;             }         }     printf("%d\n", count);     return 0; } /* 6 100100 001010 000000 110000 111000 010100 */ 


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章