| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
看到此题可以快速想到一个暴力dp。
f[i,x,y,z]表示前i次服务,第1,2,3个人的位置为x,y,z。
p[i]表示第i次服务的地点。c[i,j]表示从i到j的花费
对于第i个请求,显然只有三种决策。让x去,让y去,让z
f[i,p[i],y,z]=f[i-1,x,y,z]+c[x,p[i]] //x去
其余类推。
显然这个会超空间超时。
所以我们要减少状态。
显然在第i时刻必然有一个人的位置在p[i-1],于是只需要表示两个人的位置。
f[i,x,y]表示第i时刻 第1,2,3个人的位置为x,y,p[i-1]
则f[i-1,x,y]+c[p[i-1],p[i]]=f[i,x,y] p[i-1]换到p[i]
f[i-1,x,y]+c[y,p[i]]=f[i,x,p[i-1]] y换到p[i]
f[i-1,x,y]+c[x,p[i]]=f[i,y,p[i-1]] x换到p[i]
这个方程的解释如下
i-1 个请求后 三个位置为 x,y,p[i-1] 用f[i-1,x,y]表示
对于第i个请求,有三种决策。
x去,那么三个位置变为y,p[i-1],p[i+1] 用f[i,y,p[i-1]]表示
其余类推
var i,j,n,m,x1,x2,x3,ans:longint;
c:array[1..200,1..200]of longint;
p:array[1..1000]of longint;
f:array[0..1,1..200,1..200]of longint;
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
begin
readln(n,m);
for i:=1 to n do
begin
for j:=1 to n do
read(c[i,j]);
readln;
end;
for i:=1 to m do
read(p[i]);
fillchar(f,sizeof(f),$7f);
f[1,1,2]:=c[3,p[1]];f[1,1,3]:=c[2,p[1]];f[1,2,3]:=c[1,p[1]];
for i:=2 to m do
begin
for x1:=1 to n do
for x2:=1 to n do
begin
f[i mod 2,x1,x2]:=min(f[i mod 2,x1,x2],f[(i-1)mod 2,x1,x2]+c[p[i-1],p[i]]);
f[i mod 2,x1,p[i-1]]:=min(f[i mod 2,x1,p[i-1]],f[(i-1)mod 2,x1,x2]+c[x2,p[i]]);
f[i mod 2,x2,p[i-1]]:=min( f[i mod 2,x2,p[i-1]],f[(i-1)mod 2,x1,x2]+c[x1,p[i]]);
end;
fillchar(f[(i-1)mod 2],sizeof(f[(i-1)mod 2]),$7f);
end;
ans:=maxlongint;
if m mod 2 =1 then m:=1 else m:=0;
for i:=1 to n do
for j:=1 to n do
if ans>f[m,i,j] then ans:=f[m,i,j];
writeln(ans);
readln;readln;
end.