蓝桥杯-Car的旅行路线

链接地址: http://ayit.acmclub.com/index.php?app=problem_title&id=233&problem_id=21476

 

Car的旅行路线 分数:

时间限制:1 秒
内存限制:128 兆
特殊判题:
提交:2
解决: 1

题目描述

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

输入格式

  第一行有四个正整数s,t,A,B。
  S表示城市的个数,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个城市高速铁路单位里程的价格。

数据规模和约定
  0<S<=100,

输出

  共有n行,每行一个数据对应测试数据,保留一位小数。

样例输入

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

样例输出

47.55

 

 

最短路径问题

1)算出每个城市的第四个飞机场坐标

2)计算出4×s个点,每两个点的费用

3)Dijkstra算法找最短路

 

#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>

using namespace std ;

#define MAXN 405
#define INF 1e9

struct Point {
    int x , y ;
    Point( int x = 0 , int y = 0 ):x(x),y(y){}
};
Point data[105][4] ;    //城市飞机场的点坐标
int charge[105] ;      //高速公路的费用

Point counter( const Point &a , const Point &b , const Point &c ) { //计算矩形第四个点
     Point ab( b.x-a.x , b.y-a.y ) ;
     Point ac( c.x-a.x , c.y-a.y ) ;
     if( ab.x*ac.x + ab.y*ac.y == 0 ) return Point( b.x+c.x-a.x , b.y+c.y-a.y ) ;
     return counter( c , a , b ) ;
}

double counter( const Point &a , const Point &b ) { //计算两点的距离
    return sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) ) ;
}

struct Edge {
    int to ;
    double dist ;
    Edge( int to , double dist ):to(to),dist(dist){}
};

struct Node {
    double dist ; //到此点的距离
    int num ;    //点的编号
    Node( int num , double dist ):dist(dist),num(num){}
    bool operator < ( const Node & n ) const {  //小顶堆
        return dist > n.dist ;
    }
};

struct Dijkstra {
    int n ;   //点数
    vector<Edge> edges ; //边列表
    vector<int> G[MAXN] ; //存图
    double d[MAXN] ; //存放结果(费用)

    void init( int n ) {
        this->n = n ;
        for( int i = 1 ; i <= n ; i ++ ) {  //从1开始计数
            G[i].clear() ;
        }
        edges.clear() ;
    }

    void AddEdge( int from , int to , double dist ) {  //注意是有向图
        edges.push_back( Edge(to,dist) ) ;
        G[from].push_back( edges.size()-1 ) ;
    }

    void dijkstra( int s ) { //计算S点到所有点的距离
        for( int i = 1 ; i <= n ; i ++ ) d[i] = INF ; d[s] = 0.0 ;
        bool done[MAXN] ; memset( done , false , sizeof( done ) ) ;
        priority_queue<Node> pq ; pq.push( Node( s , 0.0 ) ) ;
        while( !pq.empty() ) {
            int u = pq.top().num ; pq.pop() ;
            if( done[u] ) continue ;
            done[u] = true ;
            for( int i = 0 ; i < G[u].size() ; i ++ ) {
                int v = edges[ G[u][i] ].to ;
                double dist = edges[ G[u][i] ].dist ;
                if( d[v] > d[u] + dist ) {
                    d[v] = d[u] + dist ;
                    pq.push( Node( v , d[v] ) ) ;
                }
            }
        }
    }

}AC;


int main() {

    int s , t , A , B ; scanf("%d%d%d%d" , &s , &t , &A , &B ) ;

    for( int i = 1 ; i <= s ; i ++ ) {   //输入数据
        for( int j = 0 ; j < 3 ; j ++ ) {
            scanf("%d%d" , &data[i][j].x , & data[i][j].y ) ;
        }
        scanf("%d" , &charge[i] ) ;
    }

    for( int i = 1 ; i <= s ; i ++ ) {  //计算第四个点
        data[i][3] = counter( data[i][0] , data[i][1] , data[i][2] ) ;
    }

    AC.init(MAXN) ;  //存图
    int n = 4*s ;
    int a_col , a_row , b_col , b_row ;
    for( int i = 0 ; i < n ; i ++ ) { //0,1,2,3为一号城市,以此类推
        a_row = i / 4 + 1 ; a_col = i % 4 ;
        for( int j = 0 ; j < n ; j ++ ) if( i != j ) { //计算任意两个点的距离
            b_row = j / 4 + 1 ; b_col = j % 4 ;
            double dist = counter( data[a_row][a_col] , data[b_row][b_col] ) ;
            if( a_row == b_row ) { //如果两个点在同一个城市,则走高速
                AC.AddEdge( i+1 , j+1 , dist*charge[a_row] ) ;
                AC.AddEdge( j+1 , i+1 , dist*charge[a_row] ) ;
            }
            else {
                AC.AddEdge( i+1 , j+1 , dist*t ) ;
                AC.AddEdge( j+1 , i+1 , dist*t ) ;
            }
        }
    }

    double res = INF ;
    for( int i = 4*(A-1)+1 ; i < 4*A+1 ; i ++ ) {  //A点的任意一个机场
        AC.dijkstra( i ) ;
        for( int j = 4*(B-1)+1 ; j < 4*B+1 ; j ++) { //B点的任意一个机场
            if( res > AC.d[j] ) res = AC.d[j] ;
        }
    }
    printf("%.1lf\n" , res ) ;

    return 0 ;
}

 

 

 

 

 

    原文作者:旅游交通路线问题
    原文地址: https://blog.csdn.net/niulinguo/article/details/84537387
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞