1210. 舞台设置

64 篇文章 0 订阅

Description

游乐园决定在一个n×m的广场上举办一次颁奖晚会,总管要你帮忙搭建一个舞台。
现在给你广场的布置图(规定地图的上方为正北),有些位置需要布置为观众席(记为1),另一些是空地(记为0)。舞台只能在空地上搭建。
为了使晚会更加吸引人,平平觉得舞台应该是朝北的h—金字塔形。h—金字塔形舞台是由h个矩形舞台相接而成的,其中后方的矩形舞台的两端必须超出在其前面的矩形舞台,且最小矩形面对的朝向为舞台的方向。下面给出几个实例:

舞台的面积应该尽量大,输出面积最大的朝北h—金字塔形舞台的面积。

Input

第一行3个整数 n、m、h。
接下来n行,每行m个0或1,中间用一个空格隔开。

Output

一个整数,表示最大的朝北的h—金字塔形舞台的面积。
如果没有符合题意的h—金字塔形舞台输出0。

Sample Input

4 6 2
0 0 1 0 0 1
0 0 0 0 0 0
0 0 1 0 0 0
0 1 1 0 0 0

Sample Output

10

Data Constraint

Hint

样例对应的最优方案如下图:

×表示观众席
【数据规模和约定】
对于10%的数据 h=1;
对于40%的数据 h≤5;
对于100%的数据 h≤20;
对于100%的数据 n、m≤100。

Solution

dp。设f[ i ][ l ][ r ][ s ]表示带第i行,选了l~r的范围作为金字塔的第s层的最大面积。

1.延续上一层:f[ i ][ l ][ r ][ s ]=f[ i-1 ][ l ][ r ][ s ]+r-l+1。

2.新建一层:f[ i ][ l ][ r ][ s ]=f[ i-1 ][ l+1~r ][ l~r-1 ][ s-1 ]+r-l+1。

时间O(nm^3h)。

优化:边做边处理处g[ i ][ l ][ r ][ s ]表示到第i行,左端点大于l,右端点小于r,做了s层的金字塔的最大面积。

g[ i ][ l ][ r ][ s ]=max{ g[ i-1 ][ l+1 ][ r ][ s ] ,g[ i-1 ][ l ][ r-1 ][ s ] ,f[ i-1 ][ l+1 ][ r-1 ][ s ] }

复杂度O(nm^2h)。

空间复杂度(nm^2h)。

开滚动数组——>(m^2h)。

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define I int
#define ll long long
#define F(i,a,b) for(I i=a;i<=b;++i)
#define Fd(i,a,b) for(I i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof(a))
#define N 110
using namespace std;
I rd(I &x){
	x=0;I w=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-') w=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	x*=w;
}
I n,m,h,a[N][N],f[2][N][N][21],g[2][N][N][21],ans,p=0;
I main(){
	freopen("Stage setting.in","r",stdin);
	freopen("Stage setting.out","w",stdout);
	rd(n),rd(m),rd(h);
	F(i,1,n){
		F(j,1,m){rd(a[i][j]);a[i][j]+=a[i][j-1];}
	}
	F(i,1,n){
		p=1-p;
		F(s,1,h) if(s<=i){
			F(len,1,m){
				F(l,1,m-len+1){
					I r=l+len-1;
					g[p][l][r][s]=max(max(g[p][l][r-1][s],g[p][l+1][r][s]),f[p][l+1][r-1][s]);
					if(!(a[i][r]-a[i][l-1])&&(s==1||g[1-p][l][r][s-1])){
						f[p][l][r][s]=max(f[1-p][l][r][s],g[1-p][l][r][s-1])+r-l+1;
						if(s==h) ans=max(ans,f[p][l][r][s]);
					}
					else f[p][l][r][s]=0;
				}
			}
		}
	}
	printf("%d\n",ans);
	return 0;
}


作者:zsjzliziyang 
QQ:1634151125 
转载及修改请注明 
本文地址:https://blog.csdn.net/zsjzliziyang/article/details/102469436

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值