又到暑假了,住在城市A的Car想和朋友一起去城市B旅游。她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一条笔直的高速铁路,第I个城市中高速铁路了的单位里程价格为Ti,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为t。
那么Car应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。
任务
找出一条从城市A到B的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。
第一行为一个正整数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个城市高速铁路单位里程的价格。
共有n行,每行一个数据对应测试数据。
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
类型:图论 难度: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; } }