题目链接

https://ac.nowcoder.com/acm/problem/20898

分析题目

说好懂也好懂,说不好理解也确实不好理解。
其实就是,跟围棋差不多,被'#'围住的都属于'#'的势力范围,而那些和边界相连的'.'则不属于'#'的势力范围。题目要求'#'的势力范围。

解题思路

如果我们的思路是遍历全部点,若为'.',从此处开始dfs/bfs,相连通的'.'都和最初开始的'.'的属性是一样的,就是说凡是dfs/bfs路径上遇到的'.'要么全是属于'#'势力范围的,要么就都不属于。当dfs/bfs到边界点的时候,开始返回,路径上的点全部标记一下不属于'#'势力范围;当dfs/bfs无法到达边界点的时候,不进行标记,路径上的点属于'#'势力范围。(有时间的话我打算写写试试)
另辟蹊径,与边界相连的连通区域是不属于'#'势力范围的。因此,我们不妨从边界'.'开始遍历,遇到的'.'必然是不属于'#'势力范围的,而没遇到的都是'#'势力范围的。我们把遇到的点都标记一下,最后遍历一遍整个图,统计未被标记点的个数,就是答案。

AC代码

//比较特殊的一点是,我用的二维数组编号进行存储的。因为直接用二维数组是开不下的。可以用vector或者string等等。
//这里不想再写一遍了,大家可以去这个题解里找一下二维数组编号的知识,挺明显的。
//https://blog.nowcoder.net/n/d18e6ea8503841f1a215250657a799cc

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int mp[N];//0代表'#',1代表'.',2代表标记不属于'#'势力范围
int n,m;
int vis[N];
int dir[4][2]={1,0,-1,0,0,1,0,-1};
void dfs(int x,int y){//类似dfs板子,稍微变了点
    mp[x*m+y]=2;//凡是能连通的'.'都赋值为2,进行标记
    for(int k=0;k<4;k++){
        int tx=x+dir[k][0],ty=y+dir[k][1];
        if(tx>=n||ty>=m||tx<0||ty<0) continue;
        if(mp[tx*m+ty]==1){//是 '.' 的情况才能进行 
            vis[tx*m+ty]=1;
            dfs(tx,ty);
            vis[tx*m+ty]=0;
        }        
    }
}
int main(){
    char ch;
    cin>>n>>m;
    for(int i=0;i<n;i++)    
        for(int j=0;j<m;j++){
            scanf(" %c",&ch);//这样能滤去空格、tab和回车
            if(ch=='#') mp[i*m+j]=0;
            if(ch=='.') mp[i*m+j]=1;
        }
    for(int i=0;i<n;i++){//遍历左边界右边界
        if(mp[i*m+0]==1) {dfs(i,0);vis[i*m+0]=1;}
        if(mp[i*m+m-1]==1) {dfs(i,m-1);vis[i*m+m-1]=1;}
    }
    for(int i=0;i<m;i++){//遍历上边界下边界
        if(mp[0*m+i]==1) {dfs(0,i);vis[0*m+i]=1;}
        if(mp[(n-1)*m+i]) {dfs(n-1,i);vis[(n-1)*m+i]=1;}
    }

    int ans=0;
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            if(mp[i*m+j]!=2)//没被标记的就是'#'的势力范围
                ans++;            
    cout<<ans;    
}

哔哔赖赖

我没做出来,因为用遍历所有'.'的方法实在没想过来,明天我试着再写写。
看着比赛中的大佬半小时解决这个题,我花了俩小时都没做对。555555QWQ
也学到了新思路,算是潜移默化的影响了一点,不亏!
最后的最后,我还想问上天一句:我什么时候才能成为大佬啊啊啊!!!