一道最短路题.

题意:

  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;
}

 

posted @ 2013-05-02 20:43  yefeng1627  阅读(150)  评论(0编辑  收藏  举报

Launch CodeCogs Equation Editor