1 1 * 3 5 *@*@* **@** *@*@* 1 8 @@****@* 5 5 ****@ *@@*@ *@**@ @@@*@ @@**@ 0 0
0 1 2 2
Mid-Central USA 1997
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1241
题意:统计字符'@'组成多少个八连块.如果两个字符'@'所在的格子相邻(横,竖或者对角线方向),就说它们属于同一个八连块.
该题属于图的遍历.有DFS和BFS.由于DFS更容易编写,一般用DFS找联通块:从每个"@"格子出发.递归遍历它周围的"@"格子.每次访问一个格子的时候就给它写上''连通分量编号"(即下面代码中的idx数组),这样就可以在访问之前检查它是否有了编号,从而避免同一格子访问多次:
#include<cstdio> #include<cstring> using namespace std; const int maxn = 100+5; char pic[maxn][maxn]; int m,n,idx[maxn][maxn]; void DFS(int r,int c,int id) { if(r<0||r>=m||c<0||c>=n) return ; if(idx[r][c]>0||pic[r][c]!='@') return ; idx[r][c]=id; for(int dr=-1;dr<=1;dr++) for(int dc=-1;dc<=1;dc++) if(dr!=0||dc!=0) DFS(r+dr,c+dc,id); } int main() { while(scanf("%d%d",&m,&n)!=EOF&&m&&n) { for(int i=0;i<m;i++) scanf("%s",pic[i]); memset(idx,0,sizeof(idx)); int cnt=0; for(int i=0;i<m;i++) for(int j=0;j<n;j++) if(idx[i][j]==0&&pic[i][j]=='@') DFS(i,j,++cnt); printf("%d\n",cnt); } return 0; }上面的代码用一个二重循环来判来找到当前格子的相邻八个格子,也可以用常量数组或者写8条DFS调用,读者可以根据自己的喜好选用.这道题的算法有个好听的名字:种子填充(floodfill).有兴趣的同学还可以看看维基百科中的动画,对DFS和BFS实现的种子填充有一个更加直观的认识.
#include<cstdio> #include <cstring> using namespace std; #define maxn 105 char a[maxn][maxn]; bool vis[maxn][maxn]; int n,m; void DFS(int x,int y) { if(x<0||x>=n||y<0||y>=m) return ;//越界 if(a[x][y]=='*'||vis[x][y]) return;//非油田||来过 vis[x][y]=true; //搜索周围八个方向 DFS(x+1,y+1); DFS(x+1,y); DFS(x+1,y-1); DFS(x,y-1); DFS(x-1,y-1); DFS(x-1,y); DFS(x-1,y+1); DFS(x,y+1); } int main() { while(scanf("%d%d",&n,&m)!=EOF) { if(n+m==0) break; for(int i=0; i<n; i++) scanf("%s",a[i]); int sum=0; memset(vis,false,sizeof(vis)); for(int i=0; i<n; i++) for(int j=0; j<m; j++) if(!vis[i][j]&&a[i][j]=='@') { DFS(i,j); sum++; } printf("%d\n",sum); } return 0; }
/* 解题思路:广度优先搜索,图的连通分量。 遍历图——>找到油田——>把油田群找出来——>标记、计数——>继续遍历——>遍历完成 只要相邻既是一起,也就是说,遍历方向有8个,所有相邻的都算。 */ #include<cstdio> #include<cstring> #include<queue> using namespace std; int n,m; char a[100][100]; int sum; int dir[8][2]={1,0,1,1,1,-1,0,1,0,-1,-1,0,-1,1,-1,-1}; //8个方向 struct node { int x; int y; }; int OK(int x,int y) { if(x>=0&&x<n&&y>=0&&y<m) return true; return false; } void bfs(int x,int y) { int i; node now,next; queue<node> q; now.x=x; now.y=y; q.push(now); while(!q.empty()) { now=q.front(); q.pop(); for(i=0;i<8;i++) { next.x=now.x+dir[i][0]; next.y=now.y+dir[i][1]; if(OK(next.x,next.y)&&a[next.x][next.y]=='@') //是油田哦 { a[next.x][next.y]='*'; //油田群遍历,标记 q.push(next); } } } } int main() { int i,j; while(scanf("%d%d",&n,&m)&&m) { sum=0; for(i=0;i<n;i++) scanf("%s",a[i]); for(i=0;i<n;i++) { for(j=0;j<m;j++) { if(a[i][j]=='@') //找到油田 { sum++; bfs(i,j); } } } printf("%d\n",sum); } return 0; }