舞台设置 (Standard IO)

题意/Description:

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

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

 

读入/Input

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

 

输出/Output

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

 

题解/solution

       明显的动态规划。
  f[i,h,x,y]表示以第i行下标为x,y的边为舞台底边且层数最大的h-舞台的面积。
  g[i,h,x,y]表示以第i行下标在x,y以内的边为舞台底边且层数最大的h-舞台的面积。即: 
  如此表示状态,不难得到转移方程:
  g[i,h,x,y]=Max{g[i,h,x,y-1],g[i,h,x+1,y],f[i,h,x+1,y-1]}
  当第i行从x至y均为0时:
  f[i,h,x,y]=Max{f[i-1,h,x,y],g[i-1,h-1,x,y]}+y-x+1
  否则:
  f[i,h,x,y]=0
  考虑到空间为O(N3h)太大了,故可将行数滚动。本题即可完美解决。

 

代码/Code

 

var
  f,c:array[0..1,0..21,0..101,0..101] of longint;
  a:array[0..101,0..101] of longint;
  n,m,h,ans:longint;
procedure init;
var
  i,j:longint;
begin
  readln(n,m,h);
  for i:=1 to n do
    for j:=1 to m do
      begin
        read(a[i,j]);
        a[i,j]:=a[i,j]+a[i,j-1];
      end;
end;

function max(o,p:longint):longint;
begin
  if o>p then exit(o);
  exit(p);
end;

procedure main;
var
  i,j,x,y,t:longint;
begin
  t:=0;
  for i:=1 to n do
    begin
      t:=1-t;
      for j:=1 to h do
        if j<=i then
          begin
            for x:=m downto 1 do
              begin
                for y:=x to m do
                  begin
                    if y-x+1>=3 then
                      c[t,j,x,y]:=max(f[t,j,x+1,y-1],max(c[t,j,x+1,y],c[t,j,x,y-1]));
                    if (a[i,y]-a[i,x-1]=0) and ((j=1) or (c[1-t,j-1,x,y]>0)) then
                      begin
                        f[t,j,x,y]:=max(f[1-t,j,x,y],c[1-t,j-1,x,y])+y-x+1;
                        if h=j then ans:=max(ans,f[t,j,x,y]);
                      end else f[t,j,x,y]:=0;
                  end;
              end;
          end;
    end;
end;

begin
  init;
  main;
  write(ans);
end.



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值