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