【动规递推】【120715测试】【朱全明NOIP模拟题】Mobile Service
样例
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.
..... 转载请注明出处 ..... http://oijzh.cnblogs.com ..... by jiangzh