对于一个蝴蝶,形状为正方形,只要左上角和右上角的点坐标确定,这个蝴蝶的大小和位置也随之确定。

那么只要枚举这两个点的坐标即可。

设三个数组:

分别表示点往下延伸、从左边延伸、从右边延伸所能到的最远距离,读入的时候顺手预处理即可。

然后枚举左上和右上点,那么翅膀宽度就是,并且一定是奇数。

而对于每个枚举的,满足条件的必须满足:

看式子可以发现,其实枚举蝴蝶边长更为简便,也就是我自己写的代码。

这样最终得到的就是答案。

注意:蝴蝶边长其实就是对角线的长度。

附代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define MAXN 2010
using namespace std;
int n,m,ans=0,map[MAXN][MAXN],leftdown[MAXN][MAXN],rightdown[MAXN][MAXN],down[MAXN][MAXN];
char tp[100000],*p1=tp,*p2=tp;
inline char get_char(){
    return p1==p2&&(p2=(p1=tp)+fread(tp,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read(){
    int date=0,w=1;char c=0;
    while(c<'0'||c>'9'){if(c=='-')w=-1;c=get_char();}
    while(c>='0'&&c<='9'){date=date*10+c-'0';c=get_char();}
    return date*w;
}
void work(){
    for(int i=1;i<=n;i++)for(int j=1,minn;j<=m;j++){
        minn=min(down[i][j],rightdown[i][j]);
        if(minn%2==0)minn--;
        for(int k=minn;k>=ans;k-=2)if(min(down[i][k+j-1],leftdown[i][k+j-1])>=k){
            ans=k;
            break;
        }
    }
    printf("%d\n",ans);
}
void init(){
    char ch;
    memset(down,0,sizeof(down));
    memset(leftdown,0,sizeof(leftdown));
    memset(rightdown,0,sizeof(rightdown));
    n=read();m=read();
    for(int i=1;i<=n;i++){
        while(ch!='O'&&ch!='X')ch=get_char();
        for(int j=1;j<=m;j++){
            if(ch=='O')map[i][j]=0;
            else if(ch=='X'){
                map[i][j]=1;
                down[i][j]=down[i-1][j]+1;
                leftdown[i][j]=leftdown[i-1][j-1]+1;
                rightdown[i][j]=rightdown[i-1][j+1]+1;
            }
            ch=get_char();
        }
    }
}
int main(){
    init();
    work();
    return 0;
}