您的位置:首页 > 其它

【计算几何】Car的旅行路线【NOIP2…

2015-02-02 19:25 288 查看
Car的旅行路线【NOIP2001提高组】
Time Limit:10000MS  Memory
Limit:65536KTotal Submit:18 Accepted:7
Description
  又到暑假了,住在城市A的Car想和朋友一起去城市B旅游。她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一条笔直的高速铁路,第I个城市中高速铁路了的单位里程价格为Ti,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为t。图例  那么Car应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。任务:  找出一条从城市A到B的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。  输入:文件输入。  输出:输出最小费用,小数点后保留1位。输入格式:  第一行为一个正整数n(0 <= n <=
10),表示有n组测试数据。  每组的第一行有四个正整数s,t,A,B。s(0 < s <=
100)表示城市的个数,t表示飞机单位里程的价格,A,B分别为城市A,B的序号,(1 <= A,B
<= S)。  接下来有S行,其中第I行均有7个正整数xi1,yi1,xi2,yi2,xi3,yi3,Ti,这当中的(xi1,yi1),(xi2,yi2),(xi3,yi3)分别是第I个城市中任意三个机场的坐标,T
I为第I个城市高速铁路单位里程的价格。输出格式:  共有n行,每行一个数据对应测试数据。样例:输入11 10 1 31 1 1 3 3 1 302 5 7 4 5 2 18 6 8 8 11 6 3输出:47.55 
Input
Output
Sample
Input


Sample
Output


Source
 
(1) 首先判断直角的位置:
  因为从测试数据文件中读入的三个点的坐标是无序的,因此需判断直角的位置,然后在计算第四个点的坐标。如图,对于线段L1、L2,如果(x1-x2)*(x3-x2)+(y1-y2)*(y3-y2)=0,那么L1
⊥ L2。  (2) 计算(x4,y4):  如图:由x4-x3=x1-x2得x4=x1-x2+x3,同样的y4=y1-y2+y3  (3) 用邻接表或邻接矩阵把各个(机场)点之间的连接关系表示出来。  (4) 计算各条高速铁路的长度l,并求出每个城市中每条高速铁路的总价:Ti * l  (5) 计算各条飞机航线的长度l',并求出每条航线的总价:t * l'  用Dijkstra计算各点间的最短路径,求出费用最少的路线。  DIJKSTRA算法算法思想:  设置一个顶点集合S并不断地作贪心选择来扩大这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度。DIJKSTRA算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,同时对数组dist做必要的修改。一旦S包含了所有V中的顶点,dist就记录了从源到所有其他顶点之间的最短路径长度。 
var r:real; n,s,t,a,b:longint; f:array[1..100*4+1,1..100*4+1]of
real; c:array[1..100,1..4,1..2]of
longint; ti:array[1..100]of
longint; procedure
make4(x1,y1,x2,y2,x3,y3,i:longint);begin if
(x2-x1)*(x3-x1)+(y2-y1)*(y3-y1)=0 then 
begin c[i,4,1]:=x3-x1+x2; c[i,4,2]:=y3-y1+y2; end;  if
(x1-x2)*(x3-x2)+(y1-y2)*(y3-y2)=0 then  begin c[i,4,1]:=x3+x1-x2;
c[i,4,2]:=y3+y1-y2; end;  if
(x2-x3)*(x1-x3)+(y2-y3)*(y1-y3)=0 then  begin c[i,4,1]:=-x3+x1+x2;
c[i,4,2]:=-y3+y1+y2; end;end; procedure
init;var i:longint;begin read(s,t,a,b); for i:=1 to s
do 
begin 
read(c[i,1,1],c[i,1,2],c[i,2,1],c[i,2,2],c[i,3,1],c[i,3,2],ti[i]); 
make4(c[i,1,1],c[i,1,2],c[i,2,1],c[i,2,2],c[i,3,1],c[i,3,2],i); 
end;end; procedure
getf;var i,j,k,k1,k2:longint;begin for i:=1 to 400
do 
for j:=1 to 400 do   if
i<>j then
f[i,j]:=maxlongint          
else f[i,j]:=0;  for k:=1 to s
do 
for i:=1 to 4 do   for
j:=1 to 4 do   
if i<>j then   
f[(k-1)*4+i,(k-1)*4+j]:=ti[k]*sqrt(sqr(c[k,i,1]-c[k,j,1])+sqr(c[k,i,2]-c[k,j,2]));  for k1:=1 to s
do 
for i:=1 to 4 do   for
k2:=1 to s do   if
k1<>k2 then   
for j:=1 to 4 do   
f[(k1-1)*4+i,(k2-1)*4+j]:=t*sqrt(sqr(c[k1,i,1]-c[k2,j,1])+sqr(c[k1,i,2]-c[k2,j,2]));end; procedure
dij(x:longint);var temp,min:real; j,mini:longint; d:array[1..400]of
real; mark:array[1..400]of
boolean;begin fillchar(mark,sizeof(mark),0); for j:=1 to 400 do
d[j]:=maxlongint; d[x]:=0;  while true
do 
begin 
min:=maxlongint; 
for j:=1 to s*4 do   if
(not mark[j])and(d[j]<min) then   
begin   
min:=d[j];   
mini:=j;   
end;  
mark[mini]:=true;    if
(mini-1) div 4=b-1 then   
begin   
if d[mini]<r then r:=d[mini];   
exit;   
end;    for
j:=1 to s*4 do   
if (not mark[j])and(f[mini,j]>0)then    
begin    
temp:=f[mini,j]+d[mini];    
if temp<d[j] then d[j]:=temp;    
end; 
end;end; procedure
main;var i:longint;begin r:=maxlongint; getf; for i:=1 to 4
do dij((a-1)*4+i); writeln(r:0:1);end; begin read(n); while
n<>0 do 
begin 
dec(n); 
init; 
main; 
end;end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: