您的位置:首页 > 其它

【动规递推】【120715测试】【朱全明NOIP模拟题】Mobile Service

2012-08-20 10:13 405 查看


样例
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.


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: