连通区域(Connected Component)一般是指图像中具有相同像素值且位置相邻的像素点组成的图像区域。每个像素点有8个邻接点,包括了上下左右和对角线的像素点。如果点a与b邻接,称之为a与b连通。如果域A与B连通,B与C连通,则A与C也连通。
试找出一个二值矩阵的所有连通域(8邻接),并给出每个连通域的面积(邻接点的个数)和重心。
每组输入包括 M+1 行,第一行输入2个整数 M (1<M<100), N (1<N<100),其中M是矩阵的行数,N是矩阵的列数。
第2至M+1行,每行 N 个整数,表示在矩阵N列的像素值(已二值化为 0 和 1, 连通域为 1 表示的区域)。
输出 K+1 行,第一行输出连通域个数K,第2至 K+1 行,每行输出3个数,依次表示为连通域的面积值和重心的坐标值(保留2位小数点),按照连通域起始点顺序输出。
4 4 0 1 0 0 0 0 0 1 0 0 0 1 1 0 0 0
3 1 1.00 0.00 2 3.00 1.50 1 0.00 3.00
class Solve: def __init__(self,arr,M,N): self.M = M self.N = N self.arr= arr; self.m_list = [] self.x_list = [] self.y_list = [] def DFS(self,i,j): if i < 0&nbs***bsp;j < 0&nbs***bsp;i == self.M&nbs***bsp;j == self.N&nbs***bsp;self.arr[i][j] == "0": return else: self.x+=int(j) self.y+=int(i) self.m+=1 self.arr[i][j] = "0" self.Dfs(i+1,j) self.Dfs(i-1,j) self.Dfs(i,j+1) self.Dfs(i,j-1) self.Dfs(i+1,j+1) self.Dfs(i-1,j+1) self.Dfs(i+1,j-1) self.Dfs(i-1,j-1) def Bfs(self,i,j): deque=[[i,j]] while(len(deque)!=0): [i,j] = deque.pop(0) if i < 0&nbs***bsp;j < 0&nbs***bsp;i == self.M&nbs***bsp;j == self.N&nbs***bsp;self.arr[i][j] == "0": continue else: deque.extend([[i-1,j-1],[i-1,j],[i-1,j+1],[i,j-1],[i,j+1],[i+1,j-1],[i+1,j],[i+1,j+1]]) self.x+=int(j) self.y+=int(i) self.m+=1 self.arr[i][j] = "0" def solve(self): for i in range(M): for j in range(N): self.m = 0 self.x =0 self.y =0 if arr[i][j] =='1': self.Bfs(i,j) #Bfs #self.Dfs(i,j) #Dfs if self.m != 0: self.m_list.append(self.m) self.x_list.append(self.x) self.y_list.append(self.y) print(len(self.m_list)) for i in range(len(self.m_list)): print("%d %.2f %.2f"%(self.m_list[i],self.x_list[i]/self.m_list[i],self.y_list[i]/self.m_list[i])) if __name__=="__main__": x = input().split() M = eval(x[0]) N = eval(x[1]) arr=[] for i in range(M): x = input().split() arr.append(x) s = Solve(arr,M,N) s.solve()
来个bfs把,bfs加值都需要注意加了这个值就必须直接置位,否则重复计算就错了。(比如我
#include <iostream> #include <vector> #include <queue> #include <tuple> using namespace std; tuple<int, float, float> bfs(vector<vector<int>>& mat,int h, int w, int y, int x){ vector<vector<int>> tracks,dirs{{-1,-1},{ 1,1}, { 1,-1},{-1,1}, { 0,-1},{-1,0}, { 0, 1},{ 1,0}}; queue<vector<int>> q; q.push({y,x}); vector<int> point; while(not q.empty()){ int n=q.size(); for(int i=0; i<n; i++){ point = q.front(), q.pop(); tracks.push_back(point); mat[point[0]][point[1]]=-1; for(auto && dir : dirs){ int ny=point[0]+dir[0],nx=point[1]+dir[1]; if(0 <= ny and ny < h and 0 <= nx and nx < w and mat[ny][nx] == 1){ q.push({ny,nx}); mat[ny][nx]=-1; // 避免重复计算! } } } } int area = tracks.size(); double my=0,mx=0; for(auto && p : tracks){ // cout<< p[0] <<" : "<<p[1]<<endl; my+=p[0],mx+=p[1]; } my/=area, mx/=area; return make_tuple(area,mx,my); } int main(){ int h,w; cin >> h >> w; vector<vector<int>> mat(h,vector<int>(w,0)); for(int y=0; y < h; y++){ for(int x=0; x < w; x++){ cin >> mat[y][x]; } } vector<tuple<int, float, float>> res; for(int y=0; y < h; y++){ for(int x=0; x < w; x++){ if(mat[y][x]==1){ res.push_back(bfs(mat,h,w,y,x)); } } } cout << res.size() << endl; for( auto && [a,b,c] : res){ printf("%d %.2f %.2f\n", a,b,c); } return 0; }
#include<iostream> #include<vector> #include<stack> using namespace std; vector<int> dx = { -1, -1, -1, 0, 0, 1, 1, 1 }; // 8连通域 vector<int> dy = { -1, 0, 1, -1, 1, -1, 0, 1 }; // 注意:这里返回值为double型 double getAverage(vector<int> nums) { double res = 0.0; for (int i = 0; i < nums.size(); i++) { res += nums[i]; } return res / nums.size(); } int main() { // input int row, col; cin >> row >> col; vector<vector<int>> grid; vector<int> v; for (int i = 0; i < row; i++) { v.clear(); for (int j = 0; j < col; j++) { int tmp; cin >> tmp; v.push_back(tmp); } grid.push_back(v); } // dfs vector<int> areas; vector<double> avg_x; vector<double> avg_y; int local_area = 0, x, y; for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (grid[i][j] == 1) { stack<pair<int, int>> stk; stk.push({ i, j }); grid[i][j] = 0; // 防止重复计算 local_area = 1; vector<int> tmp_x; vector<int> tmp_y; tmp_x.push_back(i); tmp_y.push_back(j); while (!stk.empty()) { auto au = stk.top(); stk.pop(); int r = au.first; int c = au.second; for (int k = 0; k < 8; k++) { x = r + dx[k]; y = c + dy[k]; if (x >= 0 && x < row && y >= 0 && y < col && grid[x][y] == 1) { grid[x][y] = 0; // 防止重复计算 stk.push({ x, y }); local_area++; tmp_x.push_back(x); tmp_y.push_back(y); } } } areas.push_back(local_area); avg_x.push_back(getAverage(tmp_x)); avg_y.push_back(getAverage(tmp_y)); } } } cout << areas.size() << endl; for (int i = 0; i < areas.size(); i++) { printf("%d %.2f %.2f\n", areas[i], avg_y[i], avg_x[i]); } }
import java.util.*; public class Main{ private static int[] x = new int[]{-1,0,1,1,1,0,-1,-1}; private static int[] y = new int[]{-1,-1,-1,0,1,1,1,0}; public static void main(String[] args){ Scanner in = new Scanner(System.in); int m = in.nextInt(); int n = in.nextInt(); int[][] g = new int[m][n]; int[][] st = new int[m][n]; for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ g[i][j] = in.nextInt(); } } List<double[]> list = new ArrayList<>(); List<Integer> l = new ArrayList<>(); for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ if(g[i][j] == 0 || st[i][j] == 1) continue; Queue<int[]> q = new LinkedList<>(); int sx = i, sy = j; q.offer(new int[]{i, j}); st[i][j] = 1; int cnt = 1; while(!q.isEmpty()){ int size = q.size(); for(int k=0;k<size;k++){ int[] a = q.poll(); for(int c=0;c<8;c++){ int dx = a[0]+x[c]; int dy = a[1]+y[c]; if(dx>=0 && dx<m && dy>=0 && dy<n && g[dx][dy]==1 && st[dx][dy]==0){ cnt++; q.offer(new int[]{dx,dy}); sx += dx; sy += dy; st[dx][dy] = 1; } } } } l.add(cnt); list.add(new double[]{(double)sy/cnt,(double)sx/cnt}); } } System.out.println(list.size()); for(int i=0;i<list.size();i++){ System.out.printf("%d %.2f %.2f\n", l.get(i), list.get(i)[0], list.get(i)[1]); } } }
#include <iostream> #include<vector> using namespace std; int calc(vector<vector<int> > &array, int x, int y,int &x1, int &y1) { //计算联通区域返回 联通区域的总长度 x1 y1用于计算总坐标 if(x<0 || y<0 || y==array[0].size()|| x==array.size() ||array[x][y]==0 ){ return 0; } array[x][y]=0; x1+=x; y1+=y; int len=1; int a[3]={0,-1,1}; for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ len+=calc(array, x+a[i],y+a[j],x1,y1); } } return len; } using namespace std; int main(){ int m,n; cin>>m>>n; vector<vector<int> > array(m,vector<int>(n,0)); for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ cin>>array[i][j]; } } vector<int > lenv; vector<float> x; vector<float> y; for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ if(array[i][j]==0) continue; else{ int x1=0; int y1=0; int len=calc(array,i,j,x1,y1); lenv.push_back(len); x.push_back(x1/float(len)); y.push_back(y1/float(len)); } } } printf("%d\n",lenv.size()); for(int i=0;i<lenv.size();i++){ printf("%d %0.2f %0.2f\n",lenv[i],y[i],x[i]); } system("pause"); return 0; }
#include <bits/stdc++.h> using namespace std; struct node{ bool val; pair<int, int> cnt; int nums; pair<int, int> parent; }; node P[101][101]; int M, N; pair<int, int> findParent(int i, int j){ int x =i, y =j; while(P[i][j].parent.first != i || P[i][j].parent.second != j){ int ti = P[i][j].parent.first; int tj = P[i][j].parent.second; i = ti; j = tj; } while(P[x][y].parent.first != x || P[x][y].parent.second != y){ int tx = P[x][y].parent.first; int ty = P[x][y].parent.second; P[x][y].parent = {tx, ty}; x = tx; y = ty; } return {i, j}; } void unionSet(int i, int j, int x, int y){ if(x<0 || y<0 || x>=M || y>=N) return; if(P[x][y].parent.first == -1) return; pair<int, int> p1 = findParent(i, j); pair<int, int> p2 = findParent(x, y); if(p2.first!=p1.first || p2.second!=p1.second){ P[p1.first][p1.second].nums += P[p2.first][p2.second].nums; P[p1.first][p1.second].cnt.first += P[p2.first][p2.second].cnt.first; P[p1.first][p1.second].cnt.second += P[p2.first][p2.second].cnt.second; P[p2.first][p2.second].parent = p1; } } int main(){ while(cin>>M>>N){ for(int i=0; i<M; i++){ for(int j=0; j<N; j++){ P[i][j].parent = {-1, -1}; } } int num; for(int i=0; i<M; i++){ for(int j=0; j<N; j++){ cin>>num; if(num==1) { P[i][j].val = true; P[i][j].parent = {i, j}; P[i][j].cnt = {i, j}; P[i][j].nums = 1; } else P[i][j].val = false; } } for(int i=0; i<M; i++){ for(int j=0; j<N; j++){ if(P[i][j].val){ unionSet(i, j, i-1, j-1); unionSet(i, j, i-1, j); unionSet(i, j, i-1, j+1); unionSet(i, j, i, j-1); unionSet(i, j, i, j+1); unionSet(i, j, i+1, j-1); unionSet(i, j, i+1, j); unionSet(i, j, i+1, j+1); } } } vector<int> ansnum; vector<float> ansx; vector<float> ansy; for(int i=0; i<M; i++){ for(int j=0; j<N; j++){ if(P[i][j].parent.first == i && P[i][j].parent.second == j){ int num = P[i][j].nums; int x = P[i][j].cnt.second; int y = P[i][j].cnt.first; ansnum.push_back(num); ansx.push_back(x); ansy.push_back(y); } } } int size = ansnum.size(); cout<<size<<endl; for(int i=0; i<ansnum.size(); i++){ printf("%d %.2f %.2f\n", ansnum[i], ansx[i]/ansnum[i], ansy[i]/ansnum[i]); } } return 0; }
#include<iostream> #include<vector> #include<string> #include<stdlib.h> #include<algorithm> #include<limits.h> #include <iomanip> using namespace std; void dfs(vector<vector<int>> matrix, int rows, int cols, int row, int col, vector<vector<int>>& mark, int& area, vector<pair<int, int>>& cord) { int dx[8] = {0, -1, -1, -1, 0, 1, 1, 1}; int dy[8] = {-1, -1, 0, 1, 1, 1, 0, -1}; mark[row][col] = 1; cord.push_back(make_pair(row, col)); for (int i = 0; i < 8; ++i) { int x = row + dx[i]; int y = col + dy[i]; if (x >= 0 && y >= 0 && x < rows && y < cols && mark[x][y] == 0 && matrix[x][y]) { ++area; dfs(matrix, rows, cols, x, y, mark, area, cord); } } } pair<double, double> getCordCenter(const vector<pair<int, int>>& cord) { int sumx = 0; int sumy = 0; for (pair<int, int> p : cord) { sumx += p.first; sumy += p.second; } double x_center = sumx / (double)(cord.size()); double y_center = sumy / (double)(cord.size()); pair<double, double> p = make_pair(x_center, y_center); return p; } int main() { int M, N; while (cin >> M >> N) { vector<vector<int>> matrix; for (int i = 0; i < M; ++i) { vector<int> temp; string line; for (int j = 0; j < N; ++j) { int data; cin >> data; temp.push_back(data); } matrix.push_back(temp); } // process vector<vector<int>> mark(M, vector<int>(N, 0)); int area = 1; vector<int> areas; vector<pair<double, double>> cordCenter; for (int i = 0; i < M; ++i) { for (int j = 0; j < N; ++j) { if (mark[i][j] == 0 && matrix[i][j]) { vector<pair<int, int>> cord; dfs(matrix, M, N, i, j, mark, area, cord); pair<double, double> p = getCordCenter(cord); cordCenter.push_back(p); cord.clear(); areas.push_back(area); area = 1; } } } //printVector(areas); cout << areas.size() << endl; for (unsigned int i = 0; i < areas.size(); ++i) { cout << areas[i] << " " << setiosflags(ios::fixed) << setprecision(2) << cordCenter[i].second << " " << cordCenter[i].first << endl; } } return 0; }
#include<iostream> #include<vector> #include<map> using namespace std; map<int ,vector<pair<int,int>>> loc;//count ,location map<int ,pair<double,double>> center; map<int ,int> area; void dfs(vector<vector<int>>& grid ,int i,int j ,int count) { int m = grid.size(); int n = grid[0].size(); grid[i][j] = 0; area[count]++; loc[count].push_back({i,j}); if(i-1>=0 && j-1>=0 &&grid[i-1][j-1] == 1) dfs(grid,i-1,j-1,count); if(i-1>=0 && j+1<n &&grid[i-1][j+1] == 1) dfs(grid,i-1,j+1,count); if(i-1>=0 &&grid[i-1][j] == 1) dfs(grid,i-1,j,count); if(i+1<m && j-1>=0 &&grid[i+1][j-1] == 1) dfs(grid,i+1,j-1,count); if(i+1<m && j+1<n &&grid[i+1][j+1] == 1) dfs(grid,i+1,j+1,count); if(i+1<m &&grid[i+1][j] == 1) dfs(grid,i+1,j,count); if( j-1>=0 &&grid[i][j-1] == 1) dfs(grid,i,j-1,count); if( j+1<n &&grid[i][j+1] == 1) dfs(grid,i,j+1,count); } int main() { int m,n; cin>>m>>n; int count = 0; vector<vector<int>> grid(m,vector<int>(n,0)); for(int i = 0;i<m;i++) { for(int j = 0;j<n;j++) { cin>>grid[i][j]; } } for(int i = 0;i<m;i++) { for(int j = 0;j<n;j++) { if(grid[i][j] == 1) { dfs(grid ,i,j,count); count++; } } } for(auto item:loc) { float x = 0,y = 0; int n = item.second.size(); for(int i = 0;i<n;i++) { x = x + item.second[i].first; y = y + item.second[i].second; } x = x/n; y = y/n; center[item.first] = {x,y}; } cout<<count<<endl; for(auto item:center) { cout<<area[item.first]<<" "; printf("%.2f %.2f \n",item.second.second,item.second.first); } return 0; }
#include <bits/stdc++.h> using namespace std; vector<int> area; vector<vector<pair<int,int>>> location; void dfs(vector<vector<int>>& grid,int row_i,int col_i,int& rows,int& cols,int& count) { if(row_i<0 || row_i>=rows || col_i<0 || col_i>=cols) return; if(grid[row_i][col_i]==0) return; if(area.size()==count) { area.push_back(0); location.push_back({}); } area[count]++; location[count].push_back(pair<int,int>(row_i,col_i)); grid[row_i][col_i]=0; dfs(grid,row_i+1,col_i,rows,cols,count); dfs(grid,row_i-1,col_i,rows,cols,count); dfs(grid,row_i,col_i+1,rows,cols,count); dfs(grid,row_i,col_i-1,rows,cols,count); dfs(grid,row_i-1,col_i-1,rows,cols,count); dfs(grid,row_i-1,col_i+1,rows,cols,count); dfs(grid,row_i+1,col_i-1,rows,cols,count); dfs(grid,row_i+1,col_i+1,rows,cols,count); } pair<float,float> getLoc(vector<pair<int,int>> vec) { float x = 0; float y = 0; for(auto& ins : vec) { x = x + ins.first; y = y + ins.second; } x = x/vec.size(); y = y/vec.size(); return pair<float,float>(y,x); } int main() { int m,n; cin >> m; cin >> n; if(m < 1 || n <1) { cout << 0 << endl; } vector<vector<int>>grid(m,vector<int>(n,0)); for(int i = 0;i<m;i++) { for(int j = 0;j<n;j++) { cin >> grid[i][j]; } } int count = 0; for(int i = 0;i<m;i++) { for(int j = 0;j<n;j++) { if(grid[i][j] == 1) { dfs(grid,i,j,m,n,count); count++; } } } cout << count << endl; for(int i = 0;i<area.size();i++) { cout << area[i] << " "; auto ins = getLoc(location[i]); cout << fixed<< setprecision(2) << ins.first << " " << ins.second; cout << endl; } return 0; }
M, N =list(map(int, input().split(" "))) graph = [] for _ in range(M): graph.append(list(map(int, input().split(" ")))) def dfs(i, j): count =1 col =j row =i stack =[(i, j)] visited.add((i, j)) while stack: i ,j =stack.pop() for ni ,nj in[[i, j + 1], [i, j -1], [i +1, j], [i +1, j -1], [i +1, j +1], [i -1, j], [i -1, j +1], [i -1, j -1]]: if 0 <= ni < M and 0 <= nj < N and graph[ni][nj] == 1 and(ni, nj) not in visited: count +=1 row +=ni col +=nj visited.add((ni, nj)) stack.append((ni, nj)) return(count, col, row) visited =set() result =0 li =[] for i in range(M): for j in range(N): if graph[i][j] ==1 and (i, j) not in visited: result +=1 li.append(dfs(i, j)) print(result) for count, col, row in li: print(str(count) +" {:.2f} {:.2f}".format(round(col/count, 2), round(row/count, 2)) )
#include <iostream> (720)#include <stdio.h> using namespace std; int n,m,book[101][101],a[101][101],num; float ans[100001][3],X,Y,z; int dx[]={0,1,1,1,-1,0,0-1,-1},dy[]={0,1,-1,0,0,1,-1,1,-1}; int DP(int x,int y){ if(book[x][y]==0) return 0; book[x][y]=0; X+=x,Y+=y,z++; // cout<<X<<" "<<Y<<" "<<z<<endl; int sum=1; for (int i = 1; i < 9; ++i) { if(x+dx[i]<1||x+dx[i]>m||y+dy[i]<1||y+dy[i]>n) continue; sum+=DP(x+dx[i],y+dy[i]); } return sum; } int main(){ cin>>m>>n; for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { cin>>book[i][j]; } } for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { if(book[i][j]==1){ X=0,Y=0,z=0; ans[num][0]=DP(i,j); ans[num][1]=Y/z-1; ans[num][2]=X/z-1; num++; } } } cout<<num<<endl; for (int i = 0; i < num; ++i) { printf("%.0f %.2f %.2f\n",ans[i][0],ans[i][1],ans[i][2]); } }