【动规递推】【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.

 

 

转载于:https://www.cnblogs.com/oijzh/archive/2012/08/20/2647121.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值