1. 程式人生 > 實用技巧 >NC16697P1027Car的旅行路線

NC16697P1027Car的旅行路線

連結:https://ac.nowcoder.com/acm/problem/16697
來源:牛客網

題目描述

又到暑假了,住在城市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個數據對應測試資料(最小花費)。保留一位小數。

思路:

這道題難點在於整個圖的建立和矩形第四個點的求解。

建圖

在建圖時我用\(edge[]\)陣列來存放該點的起點和終點,然後將其離散化縮為對應於\(tot\)的一個點,然後在陣列\(f[][]\)上更新其距離每個位置的邊權。

第四個點

矩形給出的三個點是一個直角三角形,我找出最長的一條邊,顯然這條邊是這個矩形的一條對角線,然後我取矩形的對角線的交點。

這個交點的座標是直角三角形斜邊的終點也即

\[\frac{x2+x3}{2}=x0\quad \frac{y2+y3}{2}=y0 \]

\[\frac{x1+x4}{2}=x0\quad \frac{y1+1y4}{2}=y0 \]

然後將兩個式子聯立:

\[\frac{x2+x3}{2}=\frac{x1+x4}{2}\quad ->\quad x4=x2+x3-x1 \]

其餘的同理。

距離

直接\(O(n^3)\)floyd就可以。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define DOF 0x7f7f7f7f
#define endl '\n'
#define mem(a,b) memset(a,b,sizeof(a))
#define debug(case,x); cout<<case<<"  : "<<x<<endl;
#define open freopen("ii.txt","r",stdin)
#define close freopen("oo.txt","w",stdout)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<long long,long long> PII;
const int maxn = 2e5 + 10;
int xa,ya,xb,yb,xc,yc,cost,xd,yd;
int s,t,a,b;

double f[410][410],c[110];
struct force{
    int id,x,y;
}edge[maxn];
double get_length(double x1,double y1,double x2,double y2){
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int tot=0;
void get_edge(){
    double dis1,dis2,dis3;
    dis1=get_length(xa,ya,xb,yb);
    dis2=get_length(xb,yb,xc,yc);
    dis3=get_length(xa,ya,xc,yc);
    if(dis1>dis2&&dis1>dis3){
        xd=xa+xb-xc;yd=ya+yb-yc;
    }else if(dis2>dis1&&dis2>dis3){
        xd=xb+xc-xa;yd=yb+yc-ya;
    }else if(dis3>dis1&&dis3>dis2){
        xd=xa+xc-xb;yd=ya+yc-yb;
    }

}
int main(){
//    open;close;
    int TT;scanf("%d",&TT);
    while(TT--){
        scanf("%d%d%d%d",&s,&t,&a,&b);
        for(int i=0;i<=4*s;++i){
            for(int j=0;j<=4*s;++j){
                if(i==j)f[i][j]=0;
                else f[i][j]=1e16;
            }
        }
        for(int p=1;p<=s;++p){
            scanf("%d%d%d%d%d%d%d",&xa,&ya,&xb,&yb,&xc,&yc,&cost);
            c[p]=cost;
            get_edge();
            edge[++tot].id=p;
            edge[tot].x=xa,edge[tot].y=ya;
            edge[++tot].id=p;
            edge[tot].x=xb,edge[tot].y=yb;
            edge[++tot].id=p;
            edge[tot].x=xc,edge[tot].y=yc;
            edge[++tot].id=p;
            edge[tot].x=xd,edge[tot].y=yd;
        }
        for(int i=1;i<=tot;++i){
            for(int j=i+1;j<=tot;++j){
                if(edge[i].id==edge[j].id){
                    f[i][j]=f[j][i]=get_length(edge[i].x,edge[i].y,edge[j].x,edge[j].y)*c[edge[i].id];
                }else{
                    f[i][j]=f[j][i]=get_length(edge[i].x,edge[i].y,edge[j].x,edge[j].y)*t;
                }
            }
        }
        for(int k=1;k<=tot;++k){
            for(int i=1;i<=tot;++i){
                for(int j=1;j<=tot;++j){
                    if(f[i][j]>f[i][k]+f[k][j])
                        f[i][j]=f[i][k]+f[k][j];
                }
            }
        }
        double ans=1e16;
        for(int i=(a-1)*4+1;i<=(a-1)*4+4;++i){
            for(int j=(b-1)*4+1;j<=b*4;++j){
                ans=min(ans,f[i][j]);
            }
        }
        printf("%.1f\n",ans);

    }

}

參考部落格:https://blog.csdn.net/lzyws739307453/article/details/85008349