黑白图像(DFS)
輸入一個(gè)n*n的黑白圖像(1表示黑色,0表示白色),任務(wù)是統(tǒng)計(jì)其中八連塊的個(gè)數(shù)。如果兩個(gè)黑格子有公共邊或者公共頂點(diǎn),就說(shuō)它們屬于同一個(gè)八連塊。如圖6-11所示的圖形有3個(gè)八連塊。
| ? | ? | ? | ? | ? | ? |
| ? | ? | ? | ? | ? | ? |
| ? | ? | ? | ? | ? | ? |
| ? | ? | ? | ? | ? | ? |
| ? | ? | ? | ? | ? | ? |
| ? | ? | ? | ? | ? | ? |
圖6-11? 擁有3個(gè)八連塊的黑白圖形
【分析】
用遞歸求解:從每個(gè)黑格子出發(fā),遞歸訪問(wèn)它所有的相鄰黑格。
int mat[MAXN][MAXN], vis[MAXN][MAXN]; void dfs(int x, int y) {if(!mat[x][y] || vis[x][y]) return; // 曾經(jīng)訪問(wèn)過(guò)這個(gè)格子,或者當(dāng)前格子是白色vis[x][y] = 1; // 標(biāo)記(x,y)已訪問(wèn)過(guò)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); // 遞歸訪問(wèn)周圍的八個(gè)格子 } 這里,黑格(x,y)的mat[x][y]為1,白格為0。為了避免同一個(gè)格子訪問(wèn)多次,用標(biāo)志vis[x][y]記錄格子(x,y)是否訪問(wèn)過(guò)。在輸入之前,在迷宮的外面加上一圈虛擬的白格子,見(jiàn)下面的程序。 memset(mat, 0, sizeof(mat)); //所有格子都初始化為白色,包括周圍一圈的虛擬格子 memset(vis, 0, sizeof(vis)); // 所有格子都沒(méi)有訪問(wèn)過(guò) 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'; // 把圖像往中間移動(dòng)一點(diǎn),空出一圈白格子 }
?
接下來(lái),只需不斷找黑格,然后調(diào)用dfs。從它出發(fā)尋找八連塊:
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); } //找到?jīng)]有訪問(wèn)過(guò)的黑格 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; //曾經(jīng)訪問(wèn)過(guò)這個(gè)格子,或者當(dāng)前 格子是白色 vis[x][y] = 1; // 標(biāo)記(x,y)已訪問(wèn)過(guò)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); // 遞歸訪問(wèn)周圍的八個(gè)格子 }int main() {char s[MAXN + 10];memset(mat, 0, sizeof(mat)); // 所有格子都初始化為白色,包括周圍 一圈的虛擬格子memset(vis, 0, sizeof(vis)); // 所有格子都沒(méi)有訪問(wèn)過(guò)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'; // 把圖像往中間移動(dòng)一點(diǎn),空出一圈白格子}int count = 0;for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++)// 找到?jīng)]有訪問(wèn)過(guò)的黑格if(!vis[i][j] && mat[i][j]) { count++; dfs(i,j); } printf("%d\n", count);return 0; }
?
上面的函數(shù)dfs就是深度優(yōu)先遍歷(Depth-FirstSearch,DFS)的算法,DFS和BFS一樣,都是從一個(gè)結(jié)點(diǎn)出發(fā),按照某種特定的次序訪問(wèn)圖中的其他特點(diǎn)。不同的是,BFS使用隊(duì)列來(lái)存放待擴(kuò)展結(jié)點(diǎn),而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; //曾經(jīng)訪問(wèn)過(guò)這個(gè)格子,或者當(dāng)前格子是白色else{map[x][y] = '0'; // 標(biāo)記(x,y)已訪問(wèn)過(guò)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); // 遞歸訪問(wèn)周圍的八個(gè)格子} }int main() {memset(map, 0, sizeof(map)); // 所有格子都沒(méi)有訪問(wèn)過(guò)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++){// 找到?jīng)]有訪問(wèn)過(guò)的黑格if(map[i][j]=='1'){dfs(i,j);count++;}}printf("%d\n", count);return 0; } /* 6 100100 001010 000000 110000 111000 010100 */
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/dyllove98/p/3226233.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
- 上一篇: 孤掌难鸣-------堵水眼
- 下一篇: Repeater嵌套绑定Repeater