题目描述

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

输入描述:

第一行为一个正整数n( 0 ≤ n ≤ 10 ),表示有n组测试数据。
每组的第一行有4个正整数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个城市中任意3个机场的坐标,Ti 为第i个城市高速铁路单位里程的价格。

输出描述:

共有n行,每行1个数据对应测试数据(最小花费)。保留一位小数。

题解

对于本题数据范围着实很小。我们直接建一个图然后跑最短路就好了。
可能只有建图写着比较麻烦吧,应该算是一个最短路裸题。具体细节看代码注释吧

代码

#include<iostream>
#include<algorithm>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<stack>
using namespace std;
#define ll long long
#define ull unsigned long long
#define pb push_back
#define pii pair<int,int>
#define all(A) A.begin(), A.end()
#define fi first
#define se second
#define MP make_pair
#define rep(i,n) for(register int i=0;i<(n);++i)
#define repi(i,a,b) for(register int i=int(a);i<=(b);++i)
#define repr(i,b,a) for(register int i=int(b);i>=(a);--i)
template<typename T>
inline T read(){
    T s=0,f=1; char ch = getchar();
    while(!isdigit(ch)) {if(ch == '-') f=-1;ch = getchar();}
    while(isdigit(ch)) {s=(s<<3)+(s<<1)+ch-48;ch = getchar();}
    return s*f;
}
#define gn() read<int>()
#define gl() read<ll>()
template<typename T>
inline void print(T x) {
    if(x<0) putchar('-'), x=-x;
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
////////////////////////////////////////////////////////////////////////
const int N=2e5+100;
struct point{
    double x, y;
    int id;
}v[450];
vector<pair<int,double> > t[450];
double powdis(point a,point b){
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
int T[105];
double dis[440];
int tot=0;
int s,tt,a,b;
double dij(){
    priority_queue<pair<double,int> >Q;
    for(int i=(a-1)*4+1;i<=a*4;++i){
        Q.push({0,i});
        dis[i]=0;
    }
    double ans=1e9;
    while(!Q.empty()){
        pair<double,int> now=Q.top();
        Q.pop();
        if(v[now.se].id==b){
            ans=min(ans,dis[now.se]);
        }
        for(auto k:t[now.se]){
            if(dis[k.fi]>dis[now.se]+k.se){
                dis[k.fi]=dis[now.se]+k.se;
                //cout<<"dis["<<k.fi<<"]="<<dis[k.fi]<<endl;
                Q.push({-dis[k.fi],k.fi});
            }
        }
    }
    return ans;
}
void solve(){
    s=gn(),tt=gn(),a=gn(),b=gn();
    repi(i,1,s){
        repi(j,1,3){
            ++tot;
            scanf("%lf%lf",&v[tot].x,&v[tot].y);
            v[tot].id=i;
        }
        scanf("%d",&T[i]);
        double ab=powdis(v[tot-2],v[tot-1]);
        double ac=powdis(v[tot-2],v[tot]);
        double bc=powdis(v[tot-1],v[tot]);
        if(ab+ac==bc){
            double x=v[tot-1].x+v[tot].x-v[tot-2].x;
            double y=v[tot-1].y+v[tot].y-v[tot-2].y;
            v[++tot]={x,y,i};
        }
        else if(ab+bc==ac){
            double x=v[tot-2].x+v[tot].x-v[tot-1].x;
            double y=v[tot-2].y+v[tot].y-v[tot-1].y;
            v[++tot]={x,y,i};
        }
        else {
            double x=v[tot-1].x+v[tot-2].x-v[tot].x;
            double y=v[tot-1].y+v[tot-2].y-v[tot].y;
            v[++tot]={x,y,i};
        }//求出第四个点
        repr(j,tot,tot-3){
            repi(k,tot-3,tot){
                if(j!=k)t[j].pb(MP(k,sqrt(powdis(v[j],v[k]))*T[i]));
            }
        }//把相同城市之间的高铁航道建好
    }
    for(int i=1;i<=tot;++i){
        dis[i]=1e9;
        for(int j=1;j<=tot;++j){
            if(v[i].id==v[j].id)continue;
            t[i].pb(MP(j,sqrt(powdis(v[i],v[j]))*tt));
        }
    }//把不同城市之间的飞机航道建好
    printf("%.1f\n",dij());//跑最短路
}
////////////////////////////////////////////////////////////////////////
int main(){
    int t;
    t=gn();
    while(t--)
        solve();
}
/**
* In every life we have some trouble
* When you worry you make it double
* Don't worry,be happy.
**/