描述 Description | |
| 又到暑假了,住在城市A的Car想和朋友一起去城市B旅游。她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一条笔直的高速铁路,第I个城市中高速铁路了的单位里程价格为Ti,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为t。 那么Car应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。找出一条从城市A到B的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。 |
| | |
| | |
| 输入格式 Input Format | |
| 第一行有四个正整数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个城市高速铁路单位里程的价格。
|
| | |
| | |
| 输出格式 Output Format | |
| 输出最小费用(结果保留两位小数) |
最短路问题,用Dijkstra算法可以完美解决。
难点在于建图。
假设未知坐标为p4(x4,y4),已知坐标分别是p1(x1,y1) p2(x2,y2) p3(x3,y3)
先根据垂直向量积为零判断每个矩形缺失的坐标位置,如果p1是p4的对角,则
(x3-x1)(x2-x1)+(y3-y1)(y2-y1)=0
由中点公式易知
x4=x3+x2-x1
y4=y3+y2-y1
下面可以开始构图了。
我构图的方案是以城市为单位,先计算内部火车线路之间的边权(火车价格*距离),然后计算该城市各机场与其他城市每一个机场之间的边权(飞机单价*距离)。这样完成以后就得到一张稠密的无向图。剩下的工作就是最短路径的标程了。
还值得注意的一点是,Dijkstra开始的时候应该把起始城市的4个机场最短距离都设为0。
#include<stdio.h>
#include<math.h>
#include<stdbool.h>
#define BIG 999999.0

void Dijkstra(void);
float dist(float x1,float y1,float x2,float y2);
void construct(void);

typedef struct

...{
float x,y;
}Point;
Point ct[100][4];
int rail[100];
int s,t,a,b;
float dis[100];
float g[400][400];

int main(void)

...{
int i,j,k;
float answer=BIG;
FILE *fin=stdin;
fscanf(fin,"%d %d %d %d ",&s,&t,&a,&b);
for(i=0;i<s;i++)
fscanf (
fin,"%f %f %f %f %f %f %d ",
&ct[i][0].x,&ct[i][0].y,
&ct[i][1].x,&ct[i][1].y,
&ct[i][2].x,&ct[i][2].y,
&rail[i]
);
construct();//构图
Dijkstra();

for (i=0;i<4;i++)...{
if(dis[(b-1)*4+i]<answer)
answer=dis[(b-1)*4+i];
}
printf("%.2f ",answer);
return 0;
}
void construct(void)

...{
int i,j,k,l;

for (i=0;i<s;i++)...{ //计算第四个点的坐标
if((ct[i][1].x-ct[i][0].x)*(ct[i][2].x-ct[i][0].x)

+(ct[i][1].y-ct[i][0].y)*(ct[i][2].y-ct[i][0].y)==0)...{
ct[i][3].x=ct[i][2].x+ct[i][1].x-ct[i][0].x;
ct[i][3].y=ct[i][2].y+ct[i][1].y-ct[i][0].y;
}else if((ct[i][0].x-ct[i][1].x)*(ct[i][2].x-ct[i][1].x)

+(ct[i][0].y-ct[i][1].y)*(ct[i][2].y-ct[i][1].y)==0)...{
ct[i][3].x=ct[i][2].x+ct[i][0].x-ct[i][1].x;
ct[i][3].y=ct[i][2].y+ct[i][0].y-ct[i][1].y;
}else if((ct[i][0].x-ct[i][2].x)*(ct[i][1].x-ct[i][2].x)

+(ct[i][0].y-ct[i][2].y)*(ct[i][1].y-ct[i][2].y)==0)...{
ct[i][3].x=ct[i][1].x+ct[i][0].x-ct[i][2].x;
ct[i][3].y=ct[i][1].y+ct[i][0].y-ct[i][2].y;
}
}

for(i=0;i<s;i++)...{//以城市为单位构图
for(j=0;j<4;j++)//城市内部
for(k=0;k<4;k++)
g[4*i+j][4*i+k]=
rail[i]*dist(ct[i][j].x,ct[i][j].y,ct[i][k].x,ct[i][k].y);

for(j=0;j<s;j++)...{//城市之间
if(j==i)continue;
for(k=0;k<4;k++)
for(l=0;l<4;l++)
g[4*i+k][4*j+l]=
t*dist(ct[i][k].x,ct[i][k].y,ct[j][l].x,ct[j][l].y);
}
}
}
float dist(float x1,float y1,float x2,float y2)

...{
return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
}
void Dijkstra(void)

...{
int i,j;
int min=BIG,minn;
bool vis[100];
memset(vis,0,sizeof(vis));
for(i=0;i<s*4;i++)
dis[i]=BIG;
dis[a-1]=dis[a]=dis[a+1]=dis[a+2]=0;

for(i=0;i<s*4;i++)...{
min=BIG;

for(j=0;j<s*4;j++)...{

if(!vis[j] && dis[j]<min)...{
min=dis[j];
minn=j;
}
}
vis[minn]=true;

for(j=0;j<4*s;j++)...{
if(min+g[minn][j]<dis[j])
dis[j]=dis[minn]+g[minn][j];
}
}
}
