题目:
思路:
这题我觉得有必要多讲讲,题目是给了我们三个阶段的分数,前四十分还是很好拿的,搜索加点优化就好了,后面就要用到动态了。
因为他说的事向左或向右杀,所以我可以认为他为了更加优化的答案就尽量的不要绕远路,就是一路向西杀到底,或者杀到一半在回来杀右边的。很幸运,我水到了60分,哈哈哈。
讲一下正解吧,首先我们要知道,如果你在路上遇到的兵就一定要杀了,所以我们可以设F[i,j],为从i到j杀的人的最大价值,因为他可以在i-j里面杀一个,两个,或者j-i+1个,所以我们循环的时候就要确定他到底杀了多少人,用k表示。
前面得出来的,每次都是要杀到一段的底,就可以退出转移方程
Fi[i,j]:=max(Fi[i+1,j]+(m-(a[i+1]-a[i])X(k-i+j)),Fj[i+1,j]+(m-(a[j]-a[i])X(k-i+j)));
Fj的同理得出。
程序:
const
maxn=1000;
var
fi,fj:array [1..maxn,1..maxn] of longint;
i,j,n,m,k,max,len:longint;
a:array [1..maxn] of longint;
function cmax(x,y:longint):longint;
begin
if x>y then exit(x)
else exit(y);
end;
begin
assign(input,'kill.in'); reset(input);
assign(output,'kill.out'); rewrite(output);
readln(n,m);
for i:=1 to n do
readln(a[i]);
for i:=1 to n-1 do
for j:=i+1 to n do
if a[i]>a[j] then
begin
a[0]:=a[i];
a[i]:=a[j];
a[j]:=a[0];
end;
for k:=1 to n do
begin
for i:=1 to n do
begin
fi[i,i]:=m-abs(a[i])*k;
fj[i,i]:=fi[i,i];
if fi[i,i]>max then max:=fi[i,i];
end;
for len:=2 to k do
for i:=1 to n-len+1 do
begin
j:=i+len-1;
fi[i,j]:=m+cmax(fi[i+1,j]-(a[i+1]-a[i])*(k-j+i),fj[i+1,j]-(a[j]-a[i])*(k-j+i));
fj[i,j]:=m+cmax(fj[i,j-1]-(a[j]-a[j-1])*(k-j+i),fi[i,j-1]-(a[j]-a[i])*(k-j+i));
end;
for i:=1 to n-k+1 do
begin
if fi[i,i+k-1]>max then max:=fi[i,i+k-1];
if fj[i,i+k-1]>max then max:=fj[i,i+k-1];
end;
end;
writeln(max);
close(input); close(output);
end.