题目描述
米尔科买了一套别墅,他想要邀请尽量多的人和他一起庆祝。他需要一张大的木质矩形桌子来让他和他的嘉宾坐下。每张桌子可容纳的人数等于它的周长(四边长度的总和)。米尔科想要买一张即可在他的公寓里放下,也可以坐下尽量多的人和他一起享用晚餐的桌子。桌子必须放置成四条边都与公寓的墙平行的样子。题目给出公寓内部的布局,请问米尔科最多可以邀请多少人吃晚餐。
输入输出格式
输入格式:
第一行包含两个整数R和S(1<=R,S<=400),代表公寓的尺寸(R为宽,S为长),以下的R行中每一行都包含了S个准确的字符(没有空格),代表这个正方形区域是没有东西的('.') ,还是有东西的('X'),米尔科只等把桌子发在没有东西的正方形区域里。
输出格式
输出米尔科在放下他的桌子后能够邀请来吃晚餐的人数
输入输出样例
输入样例#1:
2 2
..
..
输出样例#1:
7
输入样例#2:
4 4
X.XX
X..X
..X.
..XX
输出样例#2:
9
输入样例#3:
3 3
X.X
.X.
X.X
输出样例#3:
3
经过观察得出,这题需要打O(n^2)-O(n^3)的题解,先考虑O(n^3)的解
首先枚举行和列
因为需要找出1-i行可以形成的矩形,所以我们另k从i搜索到1
要成为矩形,每一行的连续空余位置都必须一样,所以sum[ i ] [ j ]表示第i行的第j列又多少个连续的空余位置
如果要每一行的连续空余位置一样并且矩阵周长最大化,那么矩阵的长度就是由目前找过最小的sum来决定
当搜索到X时,就退出,每次找到矩阵都记录一次最大值,故时间保证在O(n^3)以内
我讲的不是很清晰,希望我清晰的代码能够帮助您
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
using namespace std;
const int N=4e2+10;
int n,m;
int sum[N][N];
int maxx=0;
string s;
int read(){//弱智读入
int t;cin>>t;
return t;
}
int print(int x){//弱智输出
cout<<x<<endl;
}
int solve(int x,int y){//长和宽分别为x和y的矩阵的周长
return (x+y)<<1;
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++){
cin>>s;
for(int j=0;j<m;j++)
if(s[j]=='.')sum[i][j+1]=sum[i][j]+1;//记录前缀和
}
int minn;
for(int i=1;i<=n;i++)//枚举
for(int j=1;j<=m;j++){
minn=999999999;//记录行的最小前缀
for(int k=i;k>=1;k--){
minn=min(minn,sum[k][j]);
if(!minn)break;//当然不能为0
maxx=max(maxx,solve(i-k+1,minn));//记录最大值
}
}
print(maxx-1);return 0;
}