题目概述
回到家中的猫猫把三桶鱼全部转移到了她那长方形大池子中,然后开始思考:到底要以何种方法吃鱼呢(猫猫就是这么可爱,吃鱼也要想好吃法 ^_*)。她发现,把大池子视为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)
源程序
vara,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.