NC16697 [NOIP2001]Car的旅行路线
题目
题目描述
又到暑假了,住在城市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个数据对应测试数据(最小花费)。保留一位小数。
示例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; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/17025816.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了