8.3 脚疼

来源:互联网 发布:软件 用户使用报告 编辑:程序博客网 时间:2024/05/21 09:57

Problem 3     foot.pas/c/cpp(foot.in     foot.out )

【背景】

放暑假了,Bingo要拜访他的梦中情人XXBingo有一张地图,地图上标有从Bingo家到XX家的路线,这些路线上还有其他的MM家。Bingo想趁着放假见XX的机会顺道见见所有的MM。但是衡中把Bingo折磨的很惨:在每天急急忙忙的来回穿梭中,Bingo把脚给使坏了,不能走很多路。所以有的MM是拜访不了了,Bingo找出了几个必须拜访的MM,把她们家在地图上标了出来。Bingo想找出一条从他家出发能够经过所有必须拜访的MM家的并且能到达他的梦中情人XX家的路,并且最短。可是Bingo一想起XX就开始YY,没有任何能力思考其他事情了,所以请你来帮忙。

【题目描述】

 给出你地图上每一条路的信息以及Bingo必须拜访的MM,找出一条路,满足从Bingo家出发经过所有Bingo必须拜访的MM家(不一定按照给出的顺序拜访)并且能够到达XX家并且最短。

【输入】

第一行3个整数n,m,tn表示地图上有编号为1..nn个家,Bingo家为1XX家为n

其他MM家编号为2..n-1m表示地图上有m条路(双向)。T表示Bingo必须拜访的MMt个。

第二行为t个整数,为Bingo必须拜访的tMM家在地图上的编号。

以下m行每行有3个整数j,k,q。表示编号为j的家与编号为k的家有一条长度为q的路。(注意不只是其他MM家,也可能是Bingo家或XX,也就是jk可能等于1n)。

【输出】

一个整数 为满足条件的路的长度。

【样例】

foot.in

5 10 2

2 3

1 2 5

1 3 45

1 4 61

1 5 81

2 3 9

2 4 91

2 5 4

3 4 74

3 5 42

4 5 61

foot.out

27

 

【时间,内存限制】

 各个测试点1s64M.

【数据规模】

n<=200.

M<=20000.

T<=10.

最短路程不会超过1000000

思路:把每个必经点的单源最短路求出来,然后排列T个点的访问顺序,寻找最优解。

程序:

var
  a,d:array[1..200,1..200]of longint;
  b:array[1..200,0..200]of integer;
  v,f:array[1..200]of boolean;
  q:array[1..200000]of longint;
  vip:array[1..10]of longint;
  n,m,i,t,j,k,ans:longint;
procedure spfa(x:longint);
var
  h,t,now,i,j:longint;
begin
  for i:=1 to n do d[x,i]:=123456789;
  d[x,x]:=0;
  fillchar(v,sizeof(v),0);
  v[x]:=true;
  h:=0;t:=1;
  q[1]:=x;
  while h<t do
   begin
     h:=h+1;
     now:=q[h];
     for i:=1 to b[now,0] do
      if d[x,b[now,i]]>d[x,now]+a[now,b[now,i]] then
       begin
         d[x,b[now,i]]:=d[x,now]+a[now,b[now,i]];
         if not v[b[now,i]] then
          begin
            v[b[now,i]]:=true;
            t:=t+1;
            q[t]:=b[now,i];
          end;
       end;
     v[now]:=false;
   end;
end;
procedure init;
var
  x,y,z:longint;
begin
  readln(n,m,t);
  for i:=1 to t do read(vip[i]);
  for i:=1 to m do
   begin
     readln(x,y,z);
     inc(b[x,0]);
     b[x,b[x,0]]:=y;
     a[x,y]:=z;
     inc(b[y,0]);
     b[y,b[y,0]]:=x;
     a[y,x]:=z;
   end;
end;
procedure dfs(l,cou,x:longint);
var
  i,j:longint;
begin
  if cou<=t then
   begin
     for i:=1 to t do
      if not f[vip[i]] then
       begin
         f[vip[i]]:=true;
         dfs(l+d[x,vip[i]],cou+1,vip[i]);
         f[vip[i]]:=false;
       end;
   end
  else
     if l+d[x,n]<ans then ans:=l+d[x,n];
end;
procedure doit;
begin
  spfa(1);
  for i:=1 to t do spfa(vip[i]);
  fillchar(f,sizeof(f),0);
  ans:=maxlongint;
  dfs(0,1,1);
  writeln(ans);
end;
begin
  assign(input,'Foot.in');
  assign(output,'Foot.out');
  reset(input);
  rewrite(output);
  init;
  doit;
  close(input);
  close(output);
end.
反思:当时用spfa循环队列结果不对,很奇怪。。。以后还是少用循环队列吧。。。。

原创粉丝点击