首页 > 其他分享 >NC16697 [NOIP2001]Car的旅行路线

NC16697 [NOIP2001]Car的旅行路线

时间:2023-01-04 19:46:00浏览次数:59  
标签:NOIP2001 Car Point int NC16697 城市 idx double dis

题目链接

题目

题目描述

又到暑假了,住在城市A的Car想和朋友一起去城市B旅游。她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一条笔直的高速铁路,第I个城市中高速铁路了的单位里程价格为Ti,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为t。

img

图例(从上而下)

机场

高速铁路

飞机航线

注意:图中并没有标出所有的铁路与航线。

那么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个数据对应测试数据(最小花费)。保留一位小数。

示例1

输入

1
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.5

题解

知识点:计算几何,最短路。

难点在建图,具体看代码。

时间复杂度 \(O(s^2 \log s)\)

空间复杂度 \(O(s^2)\)

代码

#include <bits/stdc++.h>
#define ll long long

using namespace std;

template<class T>
struct Graph {
    struct edge {
        int v, nxt;
        T w;
    };
    int idx;
    vector<int> h;
    vector<edge> e;

    Graph(int n, int m) :idx(0), h(n + 1), e(m + 1) {}
    void init(int n) {
        idx = 0;
        h.assign(n + 1, 0);
    }

    void add(int u, int v, T w) {
        e[++idx] = edge{ v,h[u],w };
        h[u] = idx;
    }
};

const int N = 107 * 4, M = N * N * 2;
Graph<double> g(N, M);
int s;

struct Point {
    double x, y;
};

double dot(Point A, Point B) {
    return A.x * B.x + A.y * B.y;
}

double dist(Point A, Point B) {
    return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y));
}

double dis[N];
bool vis[N];
struct node {
    int v;
    double w;
    friend bool operator<(const node &a, const node &b) {
        return a.w > b.w;
    }
};
priority_queue<node> pq;
void dijkstra(int st) {
    for (int i = 1;i <= s * 4 + 2;i++) dis[i] = 0x3f3f3f3f, vis[i] = 0;
    dis[st] = 0;
    pq.push({ st,0 });
    while (!pq.empty()) {
        int u = pq.top().v;
        pq.pop();
        if (vis[u]) continue;
        vis[u] = 1;
        for (int i = g.h[u];i;i = g.e[i].nxt) {
            int v = g.e[i].v;
            double w = g.e[i].w;
            if (dis[v] > dis[u] + w) {
                dis[v] = dis[u] + w;
                pq.push({ v,dis[v] });
            }
        }
    }
}

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n;
    cin >> n;
    while (n--) {
        int t, A, B;
        cin >> s >> t >> A >> B;
        g.init(s * 4 + 2);
        vector<vector<Point>> v(s + 1, vector<Point>(4));
        for (int i = 1;i <= s;i++) {
            int T;
            for (int j = 0;j < 3;j++) cin >> v[i][j].x >> v[i][j].y;
            cin >> T;
            for (int j = 0;j < 3;j++) {
                if (dot({ v[i][j].x - v[i][(j + 1) % 3].x ,v[i][j].y - v[i][(j + 1) % 3].y }, { v[i][j].x - v[i][(j + 2) % 3].x ,v[i][j].y - v[i][(j + 2) % 3].y }) == 0) {
                    v[i][3].x = v[i][(j + 1) % 3].x + v[i][(j + 2) % 3].x - v[i][j].x;
                    v[i][3].y = v[i][(j + 1) % 3].y + v[i][(j + 2) % 3].y - v[i][j].y;
                    break;
                }
            }
            for (int j = 0;j < 4;j++) {
                for (int k = j + 1;k < 4;k++) {
                    double d = dist(v[i][j], v[i][k]);
                    g.add(j + 1 + 4 * (i - 1), k + 1 + 4 * (i - 1), d * T);
                    g.add(k + 1 + 4 * (i - 1), j + 1 + 4 * (i - 1), d * T);
                }
            }
        }
        for (int i = 1;i <= s;i++) {
            for (int j = 0;j < 4;j++) {
                for (int k = i + 1;k <= s;k++) {
                    for (int l = 0;l < 4;l++) {
                        double d = dist(v[i][j], v[k][l]);
                        g.add(j + 1 + 4 * (i - 1), l + 1 + 4 * (k - 1), d * t);
                        g.add(l + 1 + 4 * (k - 1), j + 1 + 4 * (i - 1), d * t);
                    }
                }
            }
        }
        for (int i = 0;i < 4;i++) g.add(s * 4 + 1, i + 1 + (A - 1) * 4, 0);
        for (int i = 0;i < 4;i++) g.add(i + 1 + (B - 1) * 4, s * 4 + 2, 0);
        dijkstra(s * 4 + 1);
        cout << fixed << setprecision(1) << dis[s * 4 + 2] << '\n';
    }
    return 0;
}

标签:NOIP2001,Car,Point,int,NC16697,城市,idx,double,dis
From: https://www.cnblogs.com/BlankYang/p/17025816.html

相关文章