例题6-12 Oil Deposits UVA - 572
【分析】
本题目求解连通块的个数,记录八连通块(向上下左右,斜向左上,斜向左下,斜向右上,斜向右下,八个方向搜素)的个数可以通过vis数组进行记录,不仅可以标记是否访问过,同时记录了已经访问到了第几个连通块。
【代码一】
/*
本程序参考刘汝佳《算法竞赛入门经典》(第2版)
*/
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=105;
int a[maxn][maxn];
char str[maxn][maxn];
int vis[maxn][maxn];//可同时记录是否被访问,还可以记录所属连通块的编号
int m,n;
void dfs(int r,int c,int cnt){
if(r<0 || r>=m || c<0 || c>=n) return;
if(vis[r][c] || str[r][c]=='*') return;
vis[r][c]=cnt;
for(int i=-1;i<=1;i++){
for(int j=-1;j<=1;j++){
if(!(i==0 && j==0)) dfs(r+i,c+j,cnt);
}
}
}
int main()
{
while(cin>>m>>n){
if(m==0) break;
for(int i=0;i<m;i++)
cin>>str[i];
memset(vis,0,sizeof(vis));
int cnt=0;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(str[i][j]=='@' && !vis[i][j]) dfs(i,j,++cnt);
}
}
cout<<cnt<<endl;
}
return 0;
}
【代码二】
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=105;
int a[maxn][maxn];
char str[maxn][maxn];
int vis[maxn][maxn];//可同时记录是否被访问,还可以记录所属连通块的编号
int m,n;
void dfs(int r,int c,int cnt){
if(r<0 || r>=m || c<0 || c>=n) return;
if(vis[r][c] || str[r][c]=='*') return;
vis[r][c]=cnt;
dfs(r+1,c+1,cnt);
dfs(r+1,c,cnt);
dfs(r+1,c-1,cnt);
dfs(r,c+1,cnt);
dfs(r,c-1,cnt);
dfs(r-1,c+1,cnt);
dfs(r-1,c,cnt);
dfs(r-1,c-1,cnt);
}
int main()
{
while(cin>>m>>n){
if(m==0) break;
for(int i=0;i<m;i++)
cin>>str[i];
memset(vis,0,sizeof(vis));
int cnt=0;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(str[i][j]=='@' && !vis[i][j]) dfs(i,j,++cnt);
}
}
cout<<cnt<<endl;
}
return 0;
}
【代码三】
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=105;
int a[maxn][maxn];
char str[maxn][maxn];
int vis[maxn][maxn];//可同时记录是否被访问,还可以记录所属连通块的编号
int dir[8][2]={1,1,1,0,1,-1,0,1,0,-1,-1,1,-1,0,-1,-1};
int m,n;
void dfs(int r,int c,int cnt){
if(r<0 || r>=m || c<0 || c>=n) return;
if(vis[r][c] || str[r][c]=='*') return;
vis[r][c]=cnt;
for(int i=0;i<8;i++){
int rr=r+dir[i][0];
int cc=c+dir[i][1];
dfs(rr,cc,cnt);
}
}
int main()
{
while(cin>>m>>n){
if(m==0) break;
for(int i=0;i<m;i++)
cin>>str[i];
memset(vis,0,sizeof(vis));
int cnt=0;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(str[i][j]=='@' && !vis[i][j]) dfs(i,j,++cnt);
}
}
cout<<cnt<<endl;
}
return 0;
}