题目描述 Description
又到暑假了,住在城市A的Car想和朋友一起去城市B旅游。她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一条笔直的高速铁路,第I个城市中高速铁路了的单位里程价格为Ti,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为t。
那么Car应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。
任务
找出一条从城市A到B的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。
输入描述 Input Description
第一行为一个正整数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个城市高速铁路单位里程的价格。
输出描述 Output Description
共有n行,每行一个数据对应测试数据。
样例输入 Sample Input
1
3 10 1 3
1 1 1 3 3 1 30
2 5 7 4 5 2 1
8 6 8 8 11 6 3
样例输出 Sample Output
类型:图论 难度:247.5
题意:给定s个机场,每个机场是个矩形,给出其中任意三个点的坐标,每个机场的四个点两两之间有公路,给出每个机场的6条公路的单位价格ti,机场之间的航线的单位价格为t,求从机场A到机场B的最小价格。
分析:
1、先求出每个矩形的第四个点的坐标,方法是先找到三个点中距离最大的两个点,即为对角线,若12为对角线,34为对角线,那么x1+x2=x3+x4,y1+y2=y3+y4,即可求出第四个点的坐标。
2、求出任意两点的直接连接的价格,若为一个机场内的点,则为dis*ti,若为两个机场的点,则为dis*t
3、遍历机场A的四个点,分别用dij方法计算其到机场B的四个点的最短路,取最小的,即为结果
注意:
1、dij方法计算单源最短路:设求点i到其他所有点最短路,那么先找到和点i距离最近的点,如j,置定j,遍历j的邻点k,若d[i][k]>d[i][j]+d[j][k],证明经过点j,i和k的距离变小,更新d[i][k]。然后继续下一循环,直到找到终点。
2、用一个标记数组f[i][j]记录已经计算出的最短路的点,若f[i][j]=1,则i到j的最短路已经算出。防止重复计算。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
using namespace std;
int s,t,a,b;
double pos[110][4][2],ti[110],w[110][4][110][4];
bool f[110][4][110][4];
void callastp(double m[][2])
{
double d01,d02,d12,d;
int a1,a2,b;
d01 = pow(m[0][0]-m[1][0],2)+pow(m[0][1]-m[1][1],2);
d02 = pow(m[0][0]-m[2][0],2)+pow(m[0][1]-m[2][1],2);
d12 = pow(m[1][0]-m[2][0],2)+pow(m[1][1]-m[2][1],2);
if(d01>=d02 && d01>=d12)
{
a1 = 0;
a2 = 1;
b = 2;
}
if(d02>=d01 && d02>=d12)
{
a1 = 0;
a2 = 2;
b = 1;
}
if(d12>=d02 && d12>=d01)
{
a1 = 1;
a2 = 2;
b = 0;
}
m[3][0] = m[a1][0]+m[a2][0]-m[b][0];
m[3][1] = m[a1][1]+m[a2][1]-m[b][1];
}
double caldis(double x[], double y[])
{
return sqrt(pow(x[0]-y[0],2)+pow(x[1]-y[1],2));
}
double dij(int m,int x,int n,int y)
{
if(m==n)
return 0;
if(f[m][x][n][y])
return w[m][x][n][y];
bool ch[110][4];
memset(ch,0,sizeof(ch));
while(1)
{
int mini,minj,minn;
mini = minj = minn = -1;
for(int i=1; i<=s; i++)
{
for(int j=0; j<4; j++)
{
if(i==m && j==x)
continue;
if(ch[i][j])
continue;
if(minn<0 || w[m][x][i][j]<minn)
{
minn = w[m][x][i][j];
mini = i;
minj = j;
}
}
}
f[m][x][mini][minj] = 1;
ch[mini][minj] = 1;
if(mini==n && minj==y)
{
//cout<<m<<" "<<x<<" "<<n<<" "<<y<<" "<<w[m][x][n][y]<<endl;
return w[m][x][n][y];
}
for(int i=1; i<=s; i++)
{
for(int j=0; j<4; j++)
{
if(w[m][x][mini][minj]+w[mini][minj][i][j]<w[m][x][i][j])
{
w[m][x][i][j] = w[m][x][mini][minj]+w[mini][minj][i][j];
}
}
}
}
}
int main()
{
int n;
cin>>n;
while(n--)
{
cin>>s>>t>>a>>b;
for(int i=1; i<=s; i++)
{
for(int j=0; j<3; j++)
cin>>pos[i][j][0]>>pos[i][j][1];
cin>>ti[i];
callastp(pos[i]);
//cout<<pos[i][3][0]<<" "<<pos[i][3][1]<<endl;
}
memset(w,0,sizeof(w));
for(int i=1; i<=s; i++)
{
for(int j=0; j<4; j++)
{
for(int k=j+1; k<4; k++)
w[i][j][i][k] = w[i][k][i][j] = caldis(pos[i][j],pos[i][k])*ti[i];
for(int k=i+1; k<=s; k++)
for(int l=0; l<4; l++)
w[i][j][k][l] = w[k][l][i][j] = caldis(pos[i][j],pos[k][l])*t;
}
}
memset(f,0,sizeof(f));
double ans = -1;
for(int i=0; i<4; i++)
{
for(int j=0; j<4; j++)
{
if(!f[a][i][b][j])
dij(a,i,b,j);
if(ans<0 || w[a][i][b][j]<ans)
ans = w[a][i][b][j];
}
}
cout<<fixed<<showpoint<<setprecision(1)<<ans<<endl;
}
}