一道最短路题.
题意:
N个城市(n<=100), 每个城市是一个矩形的(输入数据给定随机三个顶点),且四个顶点都有飞机场,城市内四个顶点移动单位花费Ti, 不同城市间通行只能坐飞机,单位花费都为m,
现在给定起点城市A,和终点城市B. 求最短花费.
解法:
首先是已知矩形三个顶点求第四个顶点. 然后拆点. 每个城市四个顶点. 城市间四个顶点只能坐火车,城市内顶点和其他城市顶点坐飞机.然后总共400个顶点.
做一次floyd,求出任意双点间最短路,然后枚举A,B的四个顶点.取最小即可.
想法很简单....代码写起来感觉不太好~~~虽然1A...
View Code
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> using namespace std; const int N = 500; const double esp = 1e-8; struct Point{ double x, y; friend Point operator - (const Point &a, const Point &b){ Point t; t.x = a.x-b.x; t.y = a.y-b.y; return t; } void input(){ scanf("%lf%lf",&x,&y); } }; int sign( double x ){ return x<-esp?-1:(x>esp); } double PointMult( Point A, Point B ){ return A.x*B.x + A.y*B.y; } double Distance( Point A, Point B ){ return sqrt( (A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y) ); } Point solve(Point A, Point B, Point C){ Point t; // BA*BC = 0 if( sign( PointMult(B-A,C-A) ) == 0 ) swap( A, B ); if( sign( PointMult(B-C,A-C) ) == 0 ) swap( C, B ); // 与坐标轴平行时 if( sign(B.x-C.x)==0 || sign(B.y-C.y)==0 ){ if( sign(B.y-C.y) == 0 ){ t.x = C.x; t.y = A.y; return t; } else{ t.x = A.x; t.y = C.y; return t; } } // 非平行 double k1 = (B.y-A.y)/(B.x-A.x), k2 = (B.y-C.y)/(B.x-C.x); double b1 = C.y-k1*C.x, b2 = A.y-k2*A.x; t.x = (b2-b1)/(k1-k2); t.y = k1*t.x+b1; return t; } struct Rec{ int t; Point p[4]; void input(){ for(int i = 0; i < 3; i++) p[i].input(); scanf("%d", &t); p[3] = solve( p[0],p[1],p[2] ); } }city[N]; int n, m, A, B; double mp[N][N]; void init(){ memset(mp,0,sizeof(mp)); for(int i = 0; i < n; i++){ mp[i][n+i] = mp[n+i][i] = city[i].t*Distance( city[i].p[0],city[i].p[1] );// (0,1) mp[i][2*n+i] = mp[2*n+i][i] = city[i].t*Distance( city[i].p[0],city[i].p[2] );// (0,2) mp[i][3*n+i] = mp[3*n+i][i] = city[i].t*Distance( city[i].p[0],city[i].p[3] );// (0,3) mp[i+n][i+2*n] = mp[i+2*n][i+n] = city[i].t*Distance( city[i].p[1],city[i].p[2] );// (1,2) mp[i+n][i+3*n] = mp[i+3*n][i+n] = city[i].t*Distance( city[i].p[1],city[i].p[3] );// (1,3) mp[i+2*n][i+3*n] = mp[i+3*n][i+2*n] = city[i].t*Distance( city[i].p[2],city[i].p[3] );// (2,3) } int M = 4*n; for(int i = 0; i < M; i++){ for(int j = 0; j < M; j++){ if( (i%n) != (j%n) ){ mp[i][j] = mp[j][i] = m*Distance( city[i%n].p[i/n], city[j%n].p[j/n] ); } } } } void floyd(){ int M = 4*n; for(int k = 0; k < M; k++) for(int i = 0; i < M; i++) for(int j = 0; j < M; j++) if( sign(mp[i][j]-(mp[i][k]+mp[k][j])) > 0 ) mp[i][j] = mp[i][k] + mp[k][j]; } int main(){ int T; scanf("%d", &T); while( T-- ){ scanf("%d%d%d%d", &n,&m,&A,&B ); for(int i = 0; i < n; i++ ) city[i].input(); init(); floyd(); A--; B--; double ans = mp[A][B]; for(int i = 0; i < 4; i++) for(int j = 0; j < 4; j++) ans = min( ans, mp[ A+i*n ][ B+j*n ] ); printf("%.1lf\n", ans ); } return 0; }