| |||
|
【解题报告】
先把船的抛锚点排个序。
f[i,j]表示前i只船且第i只船最后一点在j方格所取到的最优值。
f[i,j]:=max{f[i-1,k]+sum[j]-sum[j-c[i]]};
j和k的枚举范围需要好好琢磨一下。
program p1656;
var
ans,j,k,n,m,i:longint;
f:array[0..1,0..100001]of longint;
b,c,a,sum:array[0..100001]of longint;
procedure init;
begin
assign(input,'p1656.in');
reset(input);
assign(output,'p1656.out');
rewrite(output);
end;
procedure outit;
begin
close(input);
close(output);
end;
function min(a,b:longint):longint;
begin
if a<b then exit(a);
exit(b);
end;
function max(a,b:longint):longint;
begin
if a>b then exit(a);
exit(b);
end;
procedure qsort(l,r:longint);
var
i,j,x,t:longint;
begin
i:=l; j:=r; x:=b[(l+r) shr 1];
repeat
while b[i]<x do inc(i);
while b[j]>x do dec(j);
if not (i>j) then
begin
t:=b[i]; b[i]:=b[j]; b[j]:=t;
t:=c[i]; c[i]:=c[j]; c[j]:=t;
inc(i);
dec(j);
end;
until i>j;
if i<r then qsort(i,r);
if l<j then qsort(l,j);
end;
procedure main;
begin
readln(n);
a[n]:=0;
for i:=1 to n do read(a[i]);
for i:=1 to n do sum[i]:=sum[i-1]+a[i];
readln(m);
for i:=1 to n do read(b[i],c[i]);
qsort(1,m);
fillchar(f,sizeof(f),0);
for i:=1 to m do
for j:=max(c[i],b[i]) to min(b[i]+c[i]-1,n) do
for k:=max(c[i-1],b[i-1]) to j-c[i] do
begin
f[i and 1,j]:=max(f[i and 1,j],f[(i-1) and 1,k]+sum[j]-sum[j-c[i]]);
end;
ans:=0;
for i:=b[m] to b[m]+c[m]-1 do ans:=max(ans,f[m and 1,i]);
writeln(ans);
end;
begin
init;
main;
outit;
end.
这题数据规模不算小,于是应该想到转换方程表示,用f[i,j]表示第i条船船尾超过其锚的距离,由于不可能存在两个锚相距很远,于是j只用几百就行了;在这里,关键是转移;
g[i]表示到第i个位置时,能得到最大价值是多少;
f[i,j]=max{g[k]+sum[b[i]+j]-sum[b[i]+j-d[i]],f[i,j]}其中k在第i条船的船头左边;
g[k]=max{g[k-1],f[i,k-b[i]]};
注意:
1.更新时一定要注意枚举的范围;
2.方便起见,可以加第m+1条船,锚在n+1,宽度为1,n+1价值为0;
type ty=record d,b:longint;end;
var s:array[0..100000]of ty;
sum,g:array[0..100000]of longint;
f:array[0..100000,0..200]of longint;
n,m,i,j,k,l,ans:longint;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
procedure sort(a,b:longint);
var i,j,x:longint;
te:ty;
begin
if a>=b then exit;
i:=a;j:=b;x:=s[(i+j)div 2].b;
while i<=j do
begin
while s[i].b<x do inc(i);
while s[j].b>x do dec(j);
if i<=j then
begin
te:=s[i];s[i]:=s[j];s[j]:=te;
inc(i);dec(j);
end;
end;
sort(a,j);sort(i,b);
end;
begin
read(n);
for i:=1 to n do read(sum[i]);
for i:=1 to n do sum[i]:=sum[i]+sum[i-1];
read(m); s[m+1].b:=n+1;s[m+1].d:=1;
s[0].b:=0;s[0].d:=1;
for i:=1 to m do
read(s[i].b,s[i].d);
sort(1,m);
for i:=1 to m do
begin
for j:=max(0,s[i].d-(s[i].b-s[i-1].b)) to min(s[i].d-1,s[i+1].b-s[i].b-1) do
f[i,j]:=g[s[i].b+j-s[i].d]+sum[s[i].b+j]-sum[s[i].b+j-s[i].d];
for j:=s[i].b to s[i+1].b -1 do
begin
g[j]:=g[j-1];if f[i,j-s[i].b]>g[j] then g[j]:=f[i,j-s[i].b];
end;
end;
writeln(g[n]);
end.