对于一个蝴蝶,形状为正方形,只要左上角和右上角的点坐标确定,这个蝴蝶的大小和位置也随之确定。
那么只要枚举这两个点的坐标即可。
设三个数组:
分别表示点往下延伸、从左边延伸、从右边延伸所能到的最远距离,读入的时候顺手预处理即可。
然后枚举左上和右上点,那么翅膀宽度就是,并且一定是奇数。
而对于每个枚举的,满足条件的必须满足:
看式子可以发现,其实枚举蝴蝶边长更为简便,也就是我自己写的代码。
这样最终得到的就是答案。
注意:蝴蝶边长其实就是对角线的长度。
附代码:
#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; }