主题:[Car的旅行路线问题]又到暑假了,住在城市a的Car想和朋友一起去城市b旅游.
怜丹欣∮
[专家分:120] 发布于 2007-07-11 08:56:00
她知道每个城市有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中有两个机场之间有一条笔直的高速公路.第i个城市中高速公路的单位里程价格为Ti,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为t.
那么Car应如何安排到城市b的路线才能劲可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教.
任务:找出一条从城市a到b的旅行路线,出发和到达城市中的机场可以任意选取,要求总的花费最少.
输入文件:键盘输入文件名
输出:到屏幕(输出最小费用,小数点后保留2位)
输入格式:第一行为一个正整数n(0<=n<=10),表示有n组测试数据.每组的第一行有四个正整数s,t,a,b(s(0<s<=100)表示城市个数,t表示飞机单位的价格,a,b分别为城市a和b的序号,(1<=a<=s,1<=b<=s).接下来有s行,其中第i行均有7个正整数Xi1,Yi1,Xi2,Yi2,Xi3,Yi3,Ti,这当中的(Xi1,Yi1),(Xi2,Yi2),(Xi3,Yi3)分别是第i个城市中任意三个机场的坐标,Ti为第i个城市高速公路单位里程的价格.
输出格式:共n行,每行一个数据对应测试数据.
[size=4][color=000080]请高手帮忙解决!!谢谢!![/color][/size]
最后更新于:2007-07-11 10:28:00
回复列表 (共4个回复)
沙发
abcwuhang [专家分:1840] 发布于 2007-07-11 20:41:00
好象是NOIP2001年的题目吧~~
呼,做了半天终于做出来了....
程序:
program t2001_4;
const maxn=100;
type ZuoBiao=record (记录坐标)
x,y:integer;
end;
quee=record
num:integer;
cost:real;
end;
var s,t,a,b,i,j,k,n,n1:integer;
di,minv:real;
rail:array[1..maxn]of integer; (记录路程)
min:array[1..4*maxn]of quee; (记录最小值)
sta:array[1..4*maxn]of ZuoBiao;
function distance(a,b:ZuoBiao):real; (算两点距离)
begin
distance:=sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
end;
function dirct(i,j:integer):real;
var k,per:integer;
begin
k:=(i-1) div 4+1;
if (((i-1) div 4)=((j-1) div 4)) and (rail[k]<t) then
per:=rail[k]
else per:=t;
dirct:=distance(sta[i],sta[j])*per;
end;
procedure fourth(a,b,c:ZuoBiao;var d:ZuoBiao);
var m,n:real;
begin
if b.x=c.x then begin
d.x:=a.x;
d.y:=b.y+(a.y-c.y)*(d.x-b.x) div (a.x-c.x);
end
else if a.x=c.x then begin
d.x:=b.x;
d.y:=a.y+(b.y-c.y)*(d.x-a.x) div (b.x-c.x);
end
else begin
d.x:=(b.y-a.y)*(b.x-c.x)*(a.x-c.x)+a.x*(b.y-c.y)*(a.x-c.x)-b.x*(a.y-c.y)*(b.x-c.x);
d.x:=d.x div ((b.y-c.y)*(a.x-c.x)-(a.y-c.y)*(b.x-c.x));
d.y:=a.y+(b.y-c.y)*(d.x-a.x) div (b.x-c.x);
end;
end;
function three_one(a,b,c:ZuoBiao):ZuoBiao;
var d:ZuoBiao;ab,bc,ac:real;
begin
ab:=distance(a,b);
bc:=distance(b,c);
ac:=distance(a,c);
if (ab>bc) and (ab>ac) then
fourth(a,b,c,d)
else if (bc>ac) and (bc>ab) then
fourth(b,c,a,d)
else fourth(a,c,b,d);
three_one:=d;
end;
procedure init; (读数据,准备过程)
var d:ZuoBiao;
begin
readln(s,t,a,b);
for i:=1 to s do begin
for j:=1 to 3 do begin
read(sta[(i-1)*4+j].x);
read(sta[(i-1)*4+j].y);
end;
readln(rail[i]);
sta[(i-1)*4+4]:=three_one(sta[(i-1)*4+1],sta[(i-1)*4+2],sta[(i-1)*4+3]);
end;
end;
procedure addque(n:integer;c:real);
var p,a,a1:integer;b,b1:real;
begin
p:=1;
while (min[p].cost<>0) and (min[p].cost<=c) do
p:=p+1;
a:=min[p].num;b:=min[p].cost;
min[p].num:=n;min[p].cost:=c;
while b<>0 do begin
p:=p+1;
a1:=min[p].num;b1:=min[p].cost;
min[p].num:=a;min[p].cost:=b;
a:=a1;b:=b1;
end;
end;
procedure sort(n:integer);
var i,j:integer;temp:quee;
begin
for i:=n to 4*s-2 do
for j:=i+1 to 4*s-1 do
if min[i].cost>min[j].cost then begin
temp:=min[i];min[i]:=min[j];min[j]:=temp;end;
end;
begin
assign(input,'input4.dat'); (打开文件)
reset(input);
assign(output,'output4.dat');
rewrite(output);
readln(n);
for n1:=1 to n do begin
init;
if a=b then writeln(0.0:0:1) (判断)
else begin
minv:=1.0e20;
for j:=1 to 4 do begin
fillchar(min,sizeof(min),0);
for i:=1 to (a-1)*4+j-1 do
addque(i,dirct((a-1)*4+j,i)); (计算最小距离)
for i:=(a-1)*4+j+1 to 4*s do
addque(i,dirct((a-1)*4+j,i));
for i:=1 to 4*s-2 do begin
for k:=i+1 to 4*s-1 do begin
di:=dirct(min[i].num,min[k].num);
if (min[i].cost+di)<min[k].cost then
min[k].cost:=min[i].cost+di;
end;
sort(i+1);
end;
for k:=1 to 4*s-1 do
if (min[k].cost<minv) and ((min[k].num-1) div 4=b-1) then
minv:=min[k].cost;
end;
writeln(minv:0:1);
end;
end;
close(input);
close(output);
end.
PS:可能过程比较繁杂,但这样便于修改...
板凳
怜丹欣∮ [专家分:120] 发布于 2007-07-12 09:56:00
请abcwuhang再仔细讲解一下原理,遗迹程序的思路!谢谢!
3 楼
abcwuhang [专家分:1840] 发布于 2007-07-12 13:55:00
大概我就不讲了,其实你一步一步来仔细看应该会了解的...
关键是里面的记录语句可能看起来不太顺眼,不过把它用"with"语句改一下应该会好看一些.
4 楼
怜丹欣∮ [专家分:120] 发布于 2007-07-14 10:19:00
谢谢了!
我来回复