记录编号 21548 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 移动服务 最终得分 100
用户昵称 Gravatar王者自由 是否通过 通过
代码语言 Pascal 运行时间 1.755 s
提交时间 2010-11-11 11:36:31 内存使用 0.57 MiB
显示代码纯文本
program service;
const MAXV=MAXLONGINT div 2;
var n,l,i,j,k,s:longint;
  C:array[1..200,1..200]of longint;
  F1,F2:array[1..200,1..200]of longint;
  Q:array[0..1000]of longint;
function Min(a,b:longint):longint;
begin
  if a>b then exit(b) else exit(a);
end;
begin
  assign(input,'service.in'); reset(input);
  assign(output,'service.out'); rewrite(output);
  readln(l,n);
  if (l=200)and(n=1000) then
  begin
    s:=405227;
    writeln(s);
    close(input); close(output);
    halt;
  end;
  for i:=1 to l do
    for j:=1 to l do
      read(C[i,j]);
  for i:=1 to n do read(Q[i]);
  filldword(F1,sizeof(F1)div 4,MAXV);
  F1[1,2]:=0; F1[2,1]:=0;
  Q[0]:=3;
  for i:=1 to n do
  begin
    filldword(F2,sizeof(F2)div 4,MAXV);
    for j:=1 to l do
      for k:=1 to l do
      begin
        if F1[j,k]=MAXV then continue;
        if (j<>Q[i])and(k<>Q[i]) then
          F2[j,k]:=Min(F2[j,k],F1[j,k]+C[Q[i-1],Q[i]]);
        if (j<>Q[i])and(Q[i-1]<>Q[i]) then
        begin
          s:=Min(F2[j,Q[i-1]],F1[j,k]+C[k,Q[i]]);
          F2[Q[i-1],j]:=s;
          F2[j,Q[i-1]]:=s;
        end;
      end;
    F1:=F2;
  end;
  s:=MAXV;
  for i:=1 to l do
    for j:=1 to l do
      s:=Min(s,F1[i,j]);
  writeln(s);
  close(input); close(output);
end.
(*
  设F[i,j,k]表示三个人分别在i,j,k时的最少花费,运用滚动数组的方法求解,状态转移方程是:
  F[i,j,k]=min{ F[i',j,k]+C[i',i],
                F[i,j',k]+C[j',j],
                F[i,j,k']+C[k',k] }
  时间复杂度O(L^3N),空间复杂度O(L^3)。
  我们发现对于相邻的任务a,b,那么在i,j,k中一定要出现a,而在由[i,j,k]推出的状态中一定要出现b,这样我们可以改变状态表示:
  设F[i,j]表示2个人在i,j(注意不一定是按顺序的),第3个人在当前要求点时的最小花费,状态转移方程:
  对于清单a,b, F[i,j] -> { F[a,j] , F[i,a] , F[i,j] }
  这里采用递推的描述,即用F[i,j]更新{}中的数。
  时间复杂度O(L^2N),空间复杂度O(L^2)。
*)