样例
service.in
5 9
0 1 1 1 1
1 0 2 3 2
1 1 0 4 1
2 1 5 0 1
4 2 3 4 0
4 2 4 1 5 4 3 2 1
service.out
5
每次询问后我们都需直到三个服务员的位置,所以我们可以用一个四元组来维护状态f[i,a,b,c]表示第 i 次询问后三个服务员的位置分别在 a b c
那么 f[i,a,b,c]+cost->f[i+1,a,p[i+1],c]
->f[i+1,p[i+1],b,c]
->f[i+1,a,b,p[i+1]]
但是这样效率很低!
经过分析,我们不难发现,每次询问过后必定有一个副委员站在当前请求位置,所以就可以省取一个参数
f[i,a,b]表示当前第 i 次询问,三个服务员的位置分别为 a b 和 p[i]
f[i,a,b]+cost ->f[i+1,a,b]
->f[i+1,p[i],b]
->f[i+1,a,p[i]]
这样效率就可以大大提升!
然后就是注意处理已经有服务员在当前请求位置的情况!
Pascal Code
program service;
var
n,m:longint;
map:array[0..200+10,0..200+10] of longint;
ask:array[0..1000+10] of longint;
f:array[0..1000+10,0..200+10,0..200+10] of longint;
//f[i,a,b,c] i表示当前第几步(可用01滚动) abc分别表示三个服务员的位置(其中有一个必在当前ask[i] 可省略)
procedure init;
begin
assign(input,'service.in');
assign(output,'service.out');
reset(input);
rewrite(output);
end;
procedure outit;
begin
close(input);
close(output);
halt;
end;
procedure readdata;
var
i,j:longint;
begin
read(m,n);
for i:=1 to m do
for j:=1 to m do
read(map[i,j]);
for i:=1 to n do read(ask[i]);
end;
procedure main;
var
i,j,k,min:longint;
begin
fillchar(f,sizeof(f),$7);
f[1,1,2]:=map[3,ask[1]];
f[1,1,3]:=map[2,ask[1]];
f[1,2,3]:=map[1,ask[1]];
for i:=2 to n do
begin
if ask[i]=ask[i-1] then
begin
for j:=1 to m do
for k:=1 to m do
begin
if f[i,j,k]>f[i-1,j,k] then
begin
f[i,j,k]:=f[i-1,j,k];
f[i-1,j,k]:=-1;
end;
end;
continue;
end;
for j:=1 to m do
for k:=1 to m do
begin
if f[i-1,j,k]=-1 then continue;
if (j=ask[i])or(k=ask[i]) then//有服务员已经在请求位置
begin
if j=ask[i] then
if f[i,ask[i-1],k]>f[i-1,j,k] then
f[i,ask[i-1],k]:=f[i-1,j,k];
if k=ask[i] then
if f[i,j,ask[i-1]]>f[i-1,j,k] then
f[i,j,ask[i-1]]:=f[i-1,j,k];
continue;
end;
if f[i,j,k]>f[i-1,j,k]+map[ask[i-1],ask[i]] then
f[i,j,k]:=f[i-1,j,k]+map[ask[i-1],ask[i]];
if f[i,ask[i-1],k]>f[i-1,j,k]+map[j,ask[i]] then
f[i,ask[i-1],k]:=f[i-1,j,k]+map[j,ask[i]];
if f[i,j,ask[i-1]]>f[i-1,j,k]+map[k,ask[i]] then
f[i,j,ask[i-1]]:=f[i-1,j,k]+map[k,ask[i]];
end;
end;
min:=maxlongint;
for i:=1 to m do
begin
for j:=1 to m do
if min>f[n,i,j] then min:=f[n,i,j];
end;
writeln(min);
end;
begin
init;
readdata;
main;
outit;
end.