这里有一个减少代码量的方法:

对于一个黑子挤死两块白子的情况,可以假装填入一颗白子,再丢到dfs里计算。

注意一般情况不能用这种方法去算。

这样dfs就只用维护白子的个数和气的位置。

气的位置可能会数重,所以要用map判重(unordered_map更好)。

using namespace std;
int n,m[1001][1001],ans,cnt;
bool vis[1001][1001];
int fx[4]={1,-1,0,0},fy[4]={0,0,1,-1};
map<int,int> my;
void dfs(int x,int y)
{
    cnt++;//记录一块白子的总数
    vis[x][y]=1;
    for(int i=0;i<4;i++)
        if(!vis[x+fx[i]][y+fy[i]]&&x+fx[i]<=n&&x+fx[i]>=1&&y+fy[i]>=1&&y+fy[i]<=n)
        {
            if(m[fx[i]+x][fy[i]+y]==3)
                dfs(fx[i]+x,fy[i]+y);
            if(m[x+fx[i]][y+fy[i]]==1)
                my.insert(pair<int,int>(x+fx[i],y+fy[i]));//搜出一块白子的气的位置
        }
             
}
int main()
{
    char s;
    cin>>n;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            cin>>s;
            if(s=='.')m[i][j]=1;
            else if(s=='#')m[i][j]=2;
            else m[i][j]=3;
        }
    for(int i=1;i<=n;i++)//这里是第一次搜索,找到所有只剩一口气的白子
        for(int j=1;j<=n;j++)//这是第一种情况,维护最大值
            if(!vis[i][j]&&m[i][j]==3)
            {
                cnt=0;my.clear();
                dfs(i,j);
                if(my.size()==1)
                    ans=max(cnt,ans);
            }
    memset(vis,0,sizeof vis);//这里是第二次搜索,针对两块白子公用一气
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            if(!vis[i][j]&&m[i][j]==1)//如果此处是空地
            {
                bool tag1=0;
                for(int k=0;k<4;k++)
                    if(m[i+fx[k]][j+fy[k]]==3)
                        tag1=1;
                if(!tag1)continue;//如果周围有白子
                m[i][j]=3;//如果放入白子,代入dfs计算
                cnt=0;my.clear();
                dfs(i,j);
                if(my.size()==0)
                    ans=max(cnt-1,ans);//取出白子,数量-1
                m[i][j]=1;
            }
    cout<<ans;
}