题目
输入一个m行n列的字符矩阵,只要有两个‘@’相邻就能组成一个联通块,如下面的字符矩阵有2个联通块
****@
* @@*@
*@**@
@@@*@
@@**@
分析
将字符矩阵看作一个图,用DFS对图中的字符遍历,从每个’@’出发,遍历’@’周围的字符。每次访问时给该位置打上块标志,表示已访问,从而避免多次访问同一个位置。
代码
#include<iostream>
#include<windows.h>
#define maxn 10
using namespace std;
int m,n;
char pic[maxn][maxn];
int idx[maxn][maxn];
void dfs(int row,int col,int index){
int dr,dc;
//超过边界,返回
if(row < 0 || row >= m || col < 0 || col >=n)
return;
//不是联通块的组成部分或已访问,返回
if(pic[row][col] != '@' || idx[row][col] >0)
return;
//对符合条件的开始遍历
idx[row][col] = index;
//这里的对pic[row][col]周围元素的访问很巧妙
for(dr = -1; dr <= 1; dr++){
for(dc = -1; dc <= 1; dc++){
if(dr != 0 || dc != 0){
dfs(row+dr,col+dc,index);
}
}
}
}
int main(){
int i,j;
cin>>m>>n;
for(i = 0; i < m; i++){
for(j = 0; j < n; j++){
cin>>pic[i][j];
}
}
memset(idx,0,sizeof(idx));
int cnt = 0;
for(i = 0; i < m; i++){
for(j = 0; j < n; j++){
if(pic[i][j] == '@' && idx[i][j] == 0){ //符合块条件且未访问过
//找到一个新的
dfs(i,j,++cnt);
}
}
}
cout<<cnt<<endl;
return 0;
}