洛谷P4417 [COCI2006-2007#2] STOL

题目描述

米尔科买了一套别墅,他想要邀请尽量多的人和他一起庆祝。他需要一张大的木质矩形桌子来让他和他的嘉宾坐下。每张桌子可容纳的人数等于它的周长(四边长度的总和)。米尔科想要买一张即可在他的公寓里放下,也可以坐下尽量多的人和他一起享用晚餐的桌子。桌子必须放置成四条边都与公寓的墙平行的样子。题目给出公寓内部的布局,请问米尔科最多可以邀请多少人吃晚餐。

输入输出格式

输入格式:

第一行包含两个整数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;
}

猜你喜欢

转载自blog.csdn.net/zsyzClb/article/details/84647371