版权声明:仅供研究,转载请注明出处。 https://blog.csdn.net/CSUstudent007/article/details/83825544
思路:
很有意思的一道题,首先如果暴力遍历"*",bfs(),运行到第11个测试点就超时了,因为点比较多,是1000*1000的格子,每次bfs一个点要进行4*10^6次运算(4是因为要上下左右找一次)。也就是最大运算是10^6*4*10^6等于4*10^12,远超出计算机一次能运算的10^8.
正确思路:
遍历" . ",把"."的连通区域bfs出来,给它赋上标记,表明这些点是一个连通区域,然后记录这个连通区域的点个数,将标记与点个数作为一对存入map中,
这样我们可以得到所有的连通区域(两个连通区域不相接),对于每一个" * "来说,把它周围四个方位的点所在的连通区域的点的个数加起来再加1就是总的连通点。但此时可能会有重复的点被算进来了,因为" * "的周围的点可能就是同一个连通区域,所以,
我们采用set集合,把"*"周围的点的标记放进去去重。
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
int n,m;
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
int vis[1050][1050];
char mk[1050][1050];
struct node{
int x,y;
}nextt;
map<int,int> mm;
queue<node> q;
set<int> ss;
set<int>::iterator it;
bool check(int x,int y){
if(x<0||x>=n||y<0||y>=m) return 0;
if(vis[x][y]) return 0;
if(mk[x][y]!='.') return 0;
return 1;
}
void bfs(int sx,int sy,int ans){
int cnt=0;
node p;
p.x=sx,p.y=sy;
q.push(p);
vis[sx][sy]=ans;
while(!q.empty()){
node temp=q.front();
q.pop();
cnt++;
for(int i=0;i<4;i++){
nextt.x=temp.x+dx[i];
nextt.y=temp.y+dy[i];
if(check(nextt.x,nextt.y)){
vis[nextt.x][nextt.y]=ans;
q.push(nextt);
}
}
}
mm[ans]=cnt;//把同属于一个连通域的'.'个数放入map中
}
int main(){
int sum=0;
scanf("%d %d",&n,&m);
memset(vis,0,sizeof(vis));
int cc=1;
for(int i=0;i<n;i++) scanf("%s",mk[i]);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(mk[i][j]=='.'&&!vis[i][j]) bfs(i,j,cc++);
}
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(mk[i][j]=='*'){
sum=1;
ss.clear();
if(i>0) ss.insert(vis[i-1][j]);
if(i<n-1) ss.insert(vis[i+1][j]);
if(j>0) ss.insert(vis[i][j-1]);
if(j<m-1) ss.insert(vis[i][j+1]);
for(it=ss.begin();it!=ss.end();it++){
sum+=mm[*it];
}
sum%=10;
mk[i][j]=sum+'0';
}
}
}
for(int i=0;i<n;i++){
printf("%s\n",mk[i]);
}
return 0;
}