http://codevs.cn/problem/1748/
在一段时间内可以向规定的某一方向移动一格也可以不动,询问最大移动距离
我们用所在的格子位置作为状态,裸的复杂度为 O(N3)
我们发现朝一个方向的转移每次要 O(N) ,然后显然要转移的位置的dp+距离越大是我们想要的,所以单调队列维护 O(1) 的转移
写的好丑…
var
dp:array[0..205,0..205,0..205]of longint;
w:array[0..300,0..300]of longint;
x:array[0..300,1..2]of longint;
t:array[0..300]of longint;
i,j,k:longint;
n,m,s,a,b,c,d,e,l,r,ans:longint;
cha:char;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
begin
readln(n,m,a,b,s); dp[0,a,b]:=1;
for i:=1 to n do
begin
for j:=1 to m do
begin read(cha); if cha='.' then w[i,j]:=0 else w[i,j]:=1; end;
readln;
end;
for i:=1 to s do
begin
readln(c,d,e);
x[i,1]:=d-c+1; x[i,2]:=e;
end;
for i:=1 to s do
begin
case x[i,2] of
1:begin
for k:=1 to m do
begin
l:=1; r:=0;
for j:=n downto 1 do
begin
while (l<=r)and(t[l]-j>x[i,1]) do inc(l);
if w[j,k]=1 then begin dp[i,j,k]:=0; l:=1; r:=0; end
else
if (l<=r)and(dp[i-1,t[l],k]<>0) then dp[i,j,k]:=dp[i-1,t[l],k]+t[l]-j;
dp[i,j,k]:=max(dp[i,j,k],dp[i-1,j,k]);
while (l<=r)and(dp[i-1,t[r],k]+t[r]<dp[i-1,j,k]+j) do dec(r);
if dp[i-1,j,k]=0 then continue;
inc(r); t[r]:=j;
end;
end;
end;
2:begin
for k:=1 to m do
begin
l:=1; r:=0;
for j:=1 to n do
begin
while (l<=r)and(j-t[l]>x[i,1]) do inc(l);
if w[j,k]=1 then begin dp[i,j,k]:=0; l:=1; r:=0; end
else
if (l<=r)and(dp[i-1,t[l],k]<>0) then dp[i,j,k]:=dp[i-1,t[l],k]+j-t[l];
dp[i,j,k]:=max(dp[i,j,k],dp[i-1,j,k]);
while (l<=r)and(dp[i-1,t[r],k]-t[r]<dp[i-1,j,k]-j) do dec(r);
if dp[i-1,j,k]=0 then continue;
inc(r); t[r]:=j;
end;
end;
end;
3:begin
for j:=1 to n do
begin
l:=1; r:=0;
for k:=m downto 1 do
begin
while (l<=r)and(t[l]-k>x[i,1]) do inc(l);
if w[j,k]=1 then begin dp[i,j,k]:=0; l:=1; r:=0; end
else
if (l<=r)and(dp[i-1,j,t[l]]<>0) then dp[i,j,k]:=dp[i-1,j,t[l]]+t[l]-k;
dp[i,j,k]:=max(dp[i,j,k],dp[i-1,j,k]);
while (l<=r)and(dp[i-1,j,t[r]]+t[r]<dp[i-1,j,k]+k) do dec(r);
if dp[i-1,j,k]<>0 then begin inc(r); t[r]:=k; end;
end;
end;
end;
4:begin
for j:=1 to n do
begin
l:=1; r:=0;
for k:=1 to m do
begin
while (l<=r)and(k-t[l]>x[i,1]) do inc(l);
if w[j,k]=1 then begin dp[i,j,k]:=0; l:=1; r:=0; end
else
if (l<=r)and(dp[i-1,j,t[l]]<>0) then dp[i,j,k]:=dp[i-1,j,t[l]]+k-t[l];
dp[i,j,k]:=max(dp[i,j,k],dp[i-1,j,k]);
while (l<=r)and(dp[i-1,j,t[r]]-t[r]<dp[i-1,j,k]-k) do dec(r);
if dp[i-1,j,k]=0 then continue;
inc(r); t[r]:=k;
end;
end;
end;
end;
end;
ans:=0;
for i:=1 to n do
for j:=1 to m do
if dp[s,i,j]>ans
then ans:=dp[s,i,j];
writeln(ans-1);
end.