vijos 1119 Car的旅行路线

首先恭贺vijos复活~~~撒花~~~~

 

  又到暑假了,住在城市A的Car想和朋友一起去城市B旅游。她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一条笔直的高速铁路,第I个城市中高速铁路了的单位里程价格为Ti,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为t。
  那么Car应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。找出一条从城市A到B的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。

 

http://www.vijos.org/Problem_Show.asp?id=1119

 

额。。。这题是用最短路做的、、、就是建图的时候恶心了点,因为矩形的边可能不平行于坐标轴,在这里卡了很久。。。最后用向量积来判了。

因为很久没写了。就用了个邻接矩阵+dij,不过这题是满图,用链表也没有意义。。。可是就连最基本的dij都写错了T.T、、、错误有:

1.没有标记已经用过的点,死循环了。。。

2.外围循环用终点的dist小于初始极大值时就跳出。没有考虑到在更新过程中终点的dist也有可能被多次更新。。。

 

哎。。。最短路还得再复习。。。。

 

AC CODE:

 

program vijos_1119;
const maxn=maxlongint div 3;
      eps=1e-7;
var d:array[1..400,1..400] of real;
    dist,x,y:array[1..400] of real;
    p:array[1..400] of boolean;
    i,j,a,b,n:longint;
    ans:real;
//============================================================================
function min(x,y:real):real;
begin
  if x<y then min:=x else min:=y;
end;
//============================================================================
procedure setmap;
var i,j,g,h:longint;
    t,ti,dd:real;
begin
  readln(n,t,a,b);
  for i:=1 to n do
  begin
    j:=i*4-4;
    readln(x[j+1],y[j+1],x[j+2],y[j+2],x[j+3],y[j+3],ti);
    if abs((x[j+2]-x[j+1])*(x[j+3]-x[j+1])+(y[j+2]-y[j+1])*(y[j+3]-y[j+1]))<eps then
    begin                                         //向量积判垂直
      x[j+4]:=x[j+2]+x[j+3]-x[j+1];
      y[j+4]:=y[j+2]+y[j+3]-y[j+1];
    end else
    if abs((x[j+1]-x[j+2])*(x[j+3]-x[j+2])+(y[j+1]-y[j+2])*(y[j+3]-y[j+2]))<eps then
    begin
      x[j+4]:=x[j+1]+x[j+3]-x[j+2];
      y[j+4]:=y[j+1]+y[j+3]-y[j+2];
    end else
    begin
      x[j+4]:=x[j+1]+x[j+2]-x[j+3];
      y[j+4]:=y[j+1]+y[j+2]-y[j+3];
    end;
    for g:=j+1 to j+3 do
      for h:=g+1 to j+4 do
      begin
        dd:=sqr(x[g]-x[h])+sqr(y[g]-y[h]);
        if abs(dd)>eps then d[g,h]:=sqrt(dd)*ti else d[g,h]:=0;

        d[h,g]:=d[g,h];            //顺便判重合的情况,怕dd是一个小于零的趋近于零的值。。。
      end;
    for g:=j+1 to j+4 do
      for h:=1 to j do
      begin
        dd:=sqr(x[g]-x[h])+sqr(y[g]-y[h]);
        if abs(dd)>eps then d[g,h]:=sqrt(dd)*t else d[g,h]:=0;
        d[h,g]:=d[g,h];
      end;
  end; n:=n*4;
end;
//============================================================================
procedure walk(s,t:longint);
var i,now,next:longint;
    minn:real;
begin
  for i:=1 to n do dist[i]:=maxn;
  for i:=1 to n do p[i]:=false;            //判断已经处理过的点。
  dist[s]:=0; now:=s;
  while true do                            //是否跳出循环在循环内判断。
  begin
    minn:=maxn; next:=0; p[now]:=true;
    for i:=1 to n do
    begin
      if d[now,i]<>0 then
      dist[i]:=min(dist[i],dist[now]+d[now,i]);
      if not(p[i]) and (abs(dist[i])>0) and (dist[i]<minn) then
      begin
        minn:=dist[i];
        next:=i;
      end;
    end;
    if (next=0) or (next=t) then break;          //找不到了,或者已经找到了就跳出。
    now:=next;
  end; ans:=min(ans,dist[t]);
end;
//============================================================================
begin
  setmap; ans:=maxn;
  for i:=a*4-3 to a*4 do
    for j:=b*4-3 to b*4 do
      walk(i,j);
  writeln(ans:0:2);
end.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值