这道题是一道双调dp题。
这一题我们可以简化成A,B两个小人从n号点往左走,并且不经过相同的点。(假设A走在前面)
如果我们用f[i][j]表示快的人到达了i,慢的人到达了j所需的花费。
那么我们就可以得到一个dp方程:
f[i][i-1]=min(f[i-1][j]+abs(num[i]-num[j]));即B从后面超过了A,那么我们就可以把A,B交换,使A仍然在前面。
f[i][j]=min(f[i-1][j]+abs(num[i]-num[i-1]));即A仍然在B的前面并前进了一步。
最后,答案只要枚举B的位置就可以得到了。
代码如下:
var
a:array[0..100]of longint;
f:array[0..100,0..100]of longint;
ans,n,m,i,j,k:longint;
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
begin
while true do
begin
readln(n);
if n=0 then
break;
for i:=n downto 1 do
read(a[i]);//因为是从最左边的点出发的,所以要倒过来读入;
readln;
fillchar(f,sizeof(f),$7f);
f[1][1]:=0;
for i:=2 to n do
for j:=0 to i-1 do
begin
f[i][i-1]:=min(f[i][i-1],f[i-1][j]+abs(a[j]-a[i]));
f[i][j]:=min(f[i][j],f[i-1][j]+abs(a[i-1]-a[i]));
end;
ans:=maxlongint;
for i:=1 to n do
ans:=min(ans,f[n][i]);
writeln(ans);
end;
end.