链接地址: 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 ;
}