题解 P4417 【[COCI2006-2007#2] STOL】
评分感觉有点怪,要是数据范围给大点(例如1000)蓝题是刚好的。
提供一个思路,首先枚举桌子左下角的点,然后枚举桌子的长度,预先处理出当前点上面的最接近的墙或者上边界的距离,然后桌子的宽度是左下角的点往右延伸到的点的值取最小。时间复杂度是\(O(n^3)\)。
具体实现和其他解释在代码里,如下。
#include<bits/stdc++.h>
using namespace std;
int r,s,wsi[405][405],ans;//wsi数组保存这个点上方最接近的墙或者上边界与该点的距离
char inp;
bool cal[405][405];//保存该点是否是空地
int area(int x,int y){
int len=2147483647,res=0;
for(int j=y;j<=s&&cal[x][j];j++){//一直延伸到遇到墙或者右边界
len=min(len,wsi[x][j]);//宽度对这些点的wsi值取min。
res=max(res,len*2+(j-y+1)*2);
}
return res;
}
int main(){
cin>>r>>s;
for(int i=1;i<=r;i++)
for(int j=1;j<=s;j++){
cin>>inp;
if(inp=='.')
cal[i][j]=1;
}
for(int j=1;j<=s;j++){
int up=0;
for(int i=1;i<=r;i++){
if(cal[i][j])//该点是空地?距离值++:距离值=0;
up++;
else up=0;
wsi[i][j]=up;
}
}
for(int i=1;i<=r;i++)
for(int j=1;j<=s;j++)
if(cal[i][j])
ans=max(ans,area(i,j)-1);//ans对以每个点为左下角能够得到的最大周长值取max
cout<<ans;
}