[题目来源]:NOIP2001提高组T4
[关键字]:最短路径
[题目大意]:给定平面直角若干个矩形,计算(可经过其他矩形)两个矩形任意顶点间的最短路程费用。
//============================================================================================================
[分析]:其实题目本事没有太大的难点,只需要对每两个点进行连边(其实不用连知道坐标后现求两点间距离)然后求最短路即可。关键是如何知道给定三个顶点的矩形的另一个顶点。
公式:(x1,y1)(x2,y2)(x3,y3)为三个顶点坐标,如果(x1-x2)*(x3-x1)+(y1-y2)*(y3-y1)=0则x4=x2+x3-x1 y4=y2+y3-y1。只要循环直到找到第四个点即可,具体实现可看代码。
[代码]:
1 program project1;
2 type
3 rec = record
4 x, y, c: longint;
5 end;
6 var
7 n, tot, costf, st, ed, tc: longint;
8 pos: array[0..2000] of rec;
9 x, y: array[1..4] of longint;
10 costt: array[0..200] of longint;
11 b: array[0..200] of boolean;
12 d: array[0..100] of real;
13
14 procedure init;
15 var
16 i, j, k: longint;
17 begin
18 readln(n,costf,st,ed);
19 for i := 1 to n do
20 begin
21 readln(x[1],y[1],x[2],y[2],x[3],y[3],costt[i]);
22 for j := 1 to 3 do
23 for k := 1 to 3 do
24 if j <> k then
25 if (x[j]-x[k])*(x[6-k-j]-x[j])+(y[j]-y[k])*(y[6-k-j]-y[j]) = 0 then
26 begin
27 x[4] := x[k]+x[6-k-j]-x[j];
28 y[4] := y[k]+y[6-k-j]-y[j];
29 end;
30 for j := 1 to 4 do
31 begin
32 inc(tot);
33 pos[tot].x := x[j];
34 pos[tot].y := y[j];
35 pos[tot].c := i;
36 end;
37 end;
38 //for i := 1 to tot do writeln(pos[i].x,' ',pos[i].y,' ',pos[i].c);
39 end;
40
41 function dis(x, y: longint):real;
42 begin
43 dis := sqrt(sqr(pos[x].x-pos[y].x)+sqr(pos[x].y-pos[y].y));
44 if pos[x].c = pos[y].c then
45 dis := dis*costt[pos[x].c]
46 else dis := dis*costf;
47 end;
48
49 function dij(st: longint):real;
50 var
51 i, j, p: longint;
52 min: real;
53 begin
54 fillchar(b,sizeof(b),false);
55 fillchar(d,sizeof(d),100);
56 d[st] := 0;
57 for i := 1 to tot do
58 begin
59 min := 1e38;
60 for j := 1 to tot do
61 if (not b[j]) and (d[j] < min) then
62 begin
63 min := d[j];
64 p := j;
65 end;
66 b[p] := true;
67 for j := 1 to tot do
68 if not b[j] then
69 if d[j] > d[p]+dis(p,j) then d[j] := d[p]+dis(p,j);
70 end;
71 dij := 1e38;
72 for i := 1 to tot do
73 begin
74 if pos[i].c = ed then
75 for j := 0 to 3 do
76 if d[i+j] < dij then dij := d[i+j];
77 if pos[i].c = ed then break;
78 end;
79 end;
80
81 procedure work;
82 var
83 i, j: longint;
84 min, temp: real;
85 begin
86 min := 1e38;
87 for i := 1 to tot do
88 begin
89 if pos[i].c = st then
90 for j := 0 to 3 do
91 begin
92 temp := dij(i+j);
93 if temp < min then min := temp;
94 end;
95 if pos[i].c = st then break;
96 end;
97 writeln(min:0:1);
98 end;
99
100 begin
101 assign(input,'d:\in.txt');reset(input);
102 assign(output,'d:\out.txt');rewrite(output);
103 readln(tc);
104 while tc > 0 do
105 begin
106 init;
107 work;
108 dec(tc);
109 end;
110 close(input);
111 close(output);
112 end.