并查集+set判断个数 #include <iostream> #include <set> using namespace std; struct G{ int left; int right; int up; int down; }; const int MAXN = 50; int father[MAXN * MAXN]; //map[i][j] = father[i * n + j]对格子的编号 int m,n; G g[11] = {{1,0,1,0},{0,1,1,0},{1,0,0,1}, {0,1,0,1},{0,0,1,1},{1,1,0,0},{1,1,1,0}, {1,0,1,1},{1,1,0,1},{0,1,1,1},{1,1,1,1}}; void markSet(int m,int n){ for(int i = 0; i < m * n; i++){ father[i] = i; } } int findSet(int x){ if(father[x] != x) father[x] = findSet(father[x]); return father[x]; } void merge(int x1,int y1,int x2,int y2){ int fx = x1 * n + y1; int fy = x2 * n + y2; fx = findSet(fx); fy = findSet(fy); if(fx == fy){ return ; } else if(fx < fy){ father[fy] = fx; } else { father[fx] = fy; } } //两种连接 bool connect1(char ch1,char ch2){ if(g[ch1 - 'A'].right == 1 && g[ch2 - 'A'].left == 1) return true; else return false; } bool connect2(char ch1,char ch2){ if(g[ch1 - 'A'].down == 1 && g[ch2 - 'A'].up == 1) return true; else return false; } int main(){ char map[MAXN][MAXN]; set<int> s; while(cin >> m >> n){ if(m < 0 && n < 0) break; s.clear(); markSet(m,n); for(int i = 0; i < m ; i++){ cin >> map[i][0]; if(i != 0 && connect2(map[i - 1][0],map[i][0])){ merge(i,0,i - 1,0); } for(int j = 1; j < n; j++){ cin >> map[i][j]; if(connect1(map[i][j - 1],map[i][j])) merge(i,j - 1,i,j); if(i != 0 && connect2(map[i - 1][j],map[i][j])){ merge(i - 1,j,i,j); } } } for(int i = 0; i < m * n; i++) findSet(i); for(int i = 0; i < m * n; i++) s.insert(father[i]); cout << s.size() << endl; } return 0; }