描述 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];
}
}
}
#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];
}
}
}