洛谷 P1736 创意吃鱼法

题目概述

  回到家中的猫猫把三桶鱼全部转移到了她那长方形大池子中,然后开始思考:到底要以何种方法吃鱼呢(猫猫就是这么可爱,吃鱼也要想好吃法 ^_*)。她发现,把大池子视为01矩阵(0表示对应位置无鱼,1表示对应位置有鱼)有助于决定吃鱼策略。

  在代表池子的01矩阵中,有很多的正方形子矩阵,如果某个正方形子矩阵的某条对角线上都有鱼,且此正方形子矩阵的其他地方无鱼,猫猫就可以从这个正方形子矩阵“对角线的一端”下口,只一吸,就能把对角线上的那一队鲜鱼吸入口中。

  猫猫是个贪婪的家伙,所以她想一口吃掉尽量多的鱼。请你帮猫猫计算一下,她一口下去,最多可以吃掉多少条鱼?

  n,m≤2500

解题思路

  本题采用动态规划的思路,应该需要用滚动数组。数组a用于存放鱼的位置;la(last)表示本列中,这个格子之前有多少个连续的0,j0用于滚动;ff,fb(front,back)表示本行中,从这个格子向左与从右数有多少个连续的0;lfr,lfl(last,right,left)表示扩展到该格子时的对角线长度,fr,fl用于滚动。

  状态转移方程:fr[j]:=min(lfr[j-1]+1,ff[j-1]+1,la[j]+1);
                fl[j]:=min(lfl[j+1]+1,fb[j+1]+1,la[j]+1);

  注意最终答案可能不会出现在最后一层,因此每做一次都要比较一次答案。
  时间复杂度:O(nm)

  空间复杂度:O(nm)

源程序

var
 a,j0,fl,fr,la,ff,fb,lfl,lfr:array[0..2502]of longint;
 i,n,j,m,ans:longint;
function min3(a,b,c:longint):longint;
 begin
  if a>b then min3:=b
         else min3:=a;
  if min3>c then min3:=c;
 end;
begin
 readln(n,m);
 ans:=0;
for i:=1 to n do
  begin
   la:=j0;
   lfr:=fr;
   lfl:=fl;
   fillchar(ff,sizeof(ff),0);
   fillchar(fb,sizeof(fb),0);
   for j:=1 to m do
    begin
     read(a[j]);
     if a[j]=0 then begin
                     j0[j]:=la[j]+1;
                     ff[j]:=ff[j-1]+1;
                    end
               else begin
                     j0[j]:=0;
                     ff[j]:=0;
                    end;
    end;
   for j:=m downto 1 do
    if a[j]=0 then fb[j]:=fb[j+1]+1
              else fb[j]:=0;
   for j:=1 to m do
    begin
     fl[j]:=0;
     fr[j]:=0;
     if a[j]=1 then begin
                     fr[j]:=min3(lfr[j-1]+1,ff[j-1]+1,la[j]+1);
                     fl[j]:=min3(lfl[j+1]+1,fb[j+1]+1,la[j]+1);
                     if fr[j]>ans then ans:=fr[j];
                     if fl[j]>ans then ans:=fl[j];
                    end;
    end;
   readln;
  end;
 writeln(ans);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值