DFS+BFS-判断矩阵中块的个数
题目大意:求矩阵中块的个数
如6*7矩阵:
0 1 1 1 0 0 1
0 0 1 0 0 0 0
0 0 0 0 1 0 0
0 0 0 1 1 1 0
1 1 1 0 1 0 0
1 1 1 1 0 0 0
此矩阵中 块“1”的个数为4。
- 给出DFS做法
1 #include<bits/stdc++.h> 2 using namespace std; 3 int m,n;//m行n列 4 bool visit[20][20]=false; 5 int map_[20][20]={0}; 6 void DFS(int x,int y){ 7 int next[4][2]={0,1,0,-1,1,0,-1,0};//四个方向 8 for(int i=0;i<4;i++){ 9 int tx=x+next[i][0]; 10 int ty=y+next[i][1]; 11 if(visit[tx][ty]==true||tx<1||ty<1||tx>m||ty>n) continue;//剪枝 12 if(visit[tx][ty]==false&&map_[tx][ty]==1){ 13 visit[tx][ty]=true; 14 DFS(tx,ty); 15 } 16 } 17 } 18 int main(){ 19 while(cin>>m>>n){ 20 memset(visit,false,sizeof(visit)); 21 memset(map_,0,sizeof(map_)); 22 for(int i=1;i<=m;i++){ 23 for(int j=1;j<=n;j++){ 24 cin>>map_[i][j];//初始化地图 25 } 26 } 27 int cnt=0; 28 for(int i=1;i<=m;i++){ 29 for(int j=1;j<=n;j++){ 30 if(visit[i][j]==false&&map_[i][j]==1){ 31 //如果未被访问到 并且是能访问到的地方 32 cnt++; 33 DFS(i,j); 34 } 35 } 36 } 37 cout<<cnt<<endl; 38 } 39 return 0; 40 }
- BFS-宽度优先搜索做法:值得注意的是 BFS中设置inqueue数组是判断节点是否已入过队,而不是节点 是否已被访问(visit)。因为如果设置成是否被访问,那么可能存在某个结点已在队列中 缺未被访问 则其他节点就可访问到此节点,就会导致很多节点反复入队,这样的效率显然不如设置成是否入过队高。
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=20; 5 bool inqueue[maxn][maxn]={false}; 6 int m,n; 7 int map_[maxn][maxn]={0}; 8 int next[4][2]={0,1,1,0,0,-1,-1,0};//4个方向 9 struct Point{ 10 int x; 11 int y; 12 Point(int c,int d):x(c),y(d){} 13 }; 14 15 void BFS(int x,int y){ 16 queue<Point>q ; 17 q.push(Point(x,y));//将节点入队 18 inqueue[x][y]=true;//标记已经入过队 19 while(!q.empty()){ 20 Point top=q.front(); 21 q.pop(); 22 for(int i=0;i<4;i++){ 23 int tx=top.x+next[i][0]; 24 int ty=top.y+next[i][1]; 25 //如果超过边界;不能访问到;已经入队过 ---那么就跳过。 26 if(tx<1||ty<1||tx>m||ty>n||map_[tx][ty]==0||inqueue[tx][ty]==true) continue; 27 //否则---剩下的是合法的能访问到的 28 inqueue[tx][ty]=true;//标记入队 29 q.push(Point(tx,ty)); 30 } 31 } 32 } 33 34 int main(){ 35 while(cin>>m>>n){
memset(map_,0,sizeof(map_)); 38 memset(inqueue,false,sizeof(inqueue)); 39 for(int i=1;i<=m;i++){ 40 for(int j=1;j<=n;j++){ 41 cin>>map_[i][j];//初始化地图 42 } 43 } 44 int cnt=0; 45 for(int i=1;i<=m;i++){ 46 for(int j=1;j<=n;j++){ 47 if(inqueue[i][j]==false&&map_[i][j]==1){ 48 //如果未被访问到 并且是能访问到的地方 49 cnt++; 50 BFS(i,j); 51 } 52 } 53 } 54 cout<<cnt<<endl; 55 } 56 return 0; 57 }===================================================================================
- 2014北邮考研机试题目
-
Problem C. 图像识别
题目描述
在图像识别中,我们经常需要分析特定图像中的一些特征,而其中很重要的一点就是识别出图像的多个区域。在这个问题中,我们将给定一幅N x M的图像,其中每个1 x 1的点都用一个[0,255]的值来表示他的RGB颜色。如果两个相邻的像素点颜色差不超过D,我们就认为这两个像素点属于同一个区域。对于一个像素点(x,y) ,以下这8个点(如果存在)是与它相邻的:(x-1, y-1),(x-1,y),(x-1,y+1),(x,y-1),(x,y+1),(x+1,y-1),(x+1,y),(x+1,y+1)。
你的任务是写一个程序,分辨出给定图像中一共被分为多少个区域。
输入格式
输入数据包含多组测试数据。
输入的第一行是一个整数T(T<=100),表示测试数据的组数。
每组测试数据的第一行是三个整数N,M,D(1<=N,M<=100, 0<=D<=255),意义如上所述。
接下来N行,每行M个整数,表示给定图像的每个像素点颜色。
输出格式
对于每组测试数据输出一行,即图像中的区域数量。
输入样例
2
3 3 0
1 1 10 1 0
0 1 0
3 4 1
10 11 12 13
9 8 7 6
2 3 4 5
输出样例
1
3 - 能够看出 此题和上题大同小异,下面给出DFS做法~
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=105; 4 int n,m,d; 5 int map_[maxn][maxn]={0}; 6 bool visit[maxn][maxn]={false}; 7 int next[8][2]={-1,-1,-1,0,-1,1,0,-1,0,1,1,-1,1,0,1,1}; 8 void DFS(int x,int y){ 9 for(int i=0;i<8;i++){ 10 int tx=x+next[i][0]; 11 int ty=y+next[i][1]; 12 if(tx<0||ty<0||tx>n-1||ty>m-1||visit[tx][ty]==true) continue; 13 if(visit[tx][ty]==false&&abs(map_[x][y]-map_[tx][ty])<=d){ 14 visit[tx][ty]=true;//找到同一区域其他点并标记。 15 DFS(tx,ty); 16 } 17 } 18 } 19 int main(){ 20 int T; 21 cin>>T; 22 while(T--){ 23 memset(map_,0,sizeof(map_)); 24 memset(visit,false,sizeof(visit)); 25 cin>>n>>m>>d; 26 for(int i=0;i<n;i++){ 27 for(int j=0;j<m;j++){ 28 cin>>map_[i][j]; 29 } 30 }//初始化地图 31 int cnt=0; 32 for(int i=0;i<n;i++){ 33 for(int j=0;j<m;j++){ 34 if(visit[i][j]==false){ 35 visit[i][j]=true; 36 DFS(i,j);//找到同一区域其他点并标记。 37 /* 38 for(int i=0;i<n;i++){ 39 for(int j=0;j<m;j++){ 40 cout<<visit[i][j]<<' '; 41 } 42 cout<<endl; 43 } 44 cout<<endl; 45 */ 46 cnt++;//区域个数加1. 47 } 48 } 49 } 50 cout<<cnt<<endl; 51 } 52 return 0; 53 }

浙公网安备 33010602011771号