Advertisement
SAURAVKR

correct get travel min distance

Jan 25th, 2025
23
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.66 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. typedef double d;
  5.  
  6. struct circle {
  7.     d x, y, r;
  8. };
  9.  
  10. d dist(d x1, d y1, d x2, d y2) {
  11.     d dx = x2 - x1, dy = y2 - y1;
  12.     return sqrt(dx * dx + dy * dy);
  13. }
  14.  
  15. bool inside(const circle &circ, d x, d y) {
  16.     return dist(circ.x, circ.y, x, y) <= circ.r + 1e-9;
  17. }
  18.  
  19. d len(d ax, d ay, d bx, d by, const circle &circ) {
  20.     d l = dist(ax, ay, bx, by);
  21.     if (l < 1e-9) return 0.0;
  22.     d t = ((circ.x - ax) * (bx - ax) + (circ.y - ay) * (by - ay)) / (l * l);
  23.     t = max((d)0.0, min((d)1.0, t));
  24.     d cx = ax + t * (bx - ax), cy = ay + t * (by - ay);
  25.     d d_from_center = dist(circ.x, circ.y, cx, cy);
  26.     if (d_from_center > circ.r + 1e-9) return 0.0;
  27.     d half = sqrt(circ.r * circ.r - d_from_center * d_from_center);
  28.     d t1 = t - half / l, t2 = t + half / l;
  29.     t1 = max((d)0.0, t1), t2 = min((d)1.0, t2);
  30.     return (t2 - t1) * l;
  31. }
  32.  
  33. struct union_find {
  34.     vector<int> parent;
  35.     union_find(int n) : parent(n) { iota(parent.begin(), parent.end(), 0); }
  36.     int find(int a) {
  37.         if (parent[a] != a) parent[a] = find(parent[a]);
  38.         return parent[a];
  39.     }
  40.     void join(int a, int b) {
  41.         a = find(a), b = find(b);
  42.         if (a != b) parent[a] = b;
  43.     }
  44. };
  45.  
  46. int minDistance(vector<int> &a, vector<int> &b, vector<vector<int>> &lights) {
  47.     d ax = a[0], ay = a[1], bx = b[0], by = b[1];
  48.     int n = lights.size();
  49.     vector<circle> circles(n);
  50.     for (int i = 0; i < n; ++i) {
  51.         circles[i] = {static_cast<d>(lights[i][0]), static_cast<d>(lights[i][1]), static_cast<d>(lights[i][2])};
  52.     }
  53.  
  54.     vector<int> a_inside, b_inside;
  55.     for (int i = 0; i < n; ++i) {
  56.         if (inside(circles[i], ax, ay)) a_inside.push_back(i);
  57.         if (inside(circles[i], bx, by)) b_inside.push_back(i);
  58.     }
  59.     if (!a_inside.empty() && !b_inside.empty()) {
  60.         union_find uf(n);
  61.         for (int i = 0; i < n; ++i) {
  62.             for (int j = i + 1; j < n; ++j) {
  63.                 if (dist(circles[i].x, circles[i].y, circles[j].x, circles[j].y) <= circles[i].r + circles[j].r + 1e-9) {
  64.                     uf.join(i, j);
  65.                 }
  66.             }
  67.         }
  68.         for (int i : a_inside) {
  69.             for (int j : b_inside) {
  70.                 if (uf.find(i) == uf.find(j)) {
  71.                     return 0;
  72.                 }
  73.             }
  74.         }
  75.     }
  76.  
  77.     int s = 0, e = 1, base = 2, tot = base + n;
  78.     vector<d> dists(tot, 1e18);
  79.     dists[s] = 0.0;
  80.     priority_queue<pair<d, int>, vector<pair<d, int>>, greater<pair<d, int>>> q;
  81.     q.push(make_pair(0.0, s));
  82.  
  83.     while (!q.empty()) {
  84.         pair<d, int> top = q.top();
  85.         q.pop();
  86.         d cur = top.first;
  87.         int u = top.second;
  88.         if (cur > dists[u] + 1e-9) continue;
  89.  
  90.         if (u == s) {
  91.             for (int i = 0; i < n; ++i) {
  92.                 d edge = max((d)0.0, dist(ax, ay, circles[i].x, circles[i].y) - circles[i].r);
  93.                 int v = base + i;
  94.                 if (dists[v] > cur + edge) {
  95.                     dists[v] = cur + edge;
  96.                     q.push(make_pair(dists[v], v));
  97.                 }
  98.             }
  99.             d ab = dist(ax, ay, bx, by), mx = 0.0;
  100.             for (auto &circ : circles) mx = max(mx, len(ax, ay, bx, by, circ));
  101.             d edge = max(ab - mx, (d)0.0);
  102.             if (dists[e] > cur + edge) {
  103.                 dists[e] = cur + edge;
  104.                 q.push(make_pair(dists[e], e));
  105.             }
  106.         } else if (u == e) {
  107.             continue;
  108.         } else {
  109.             int ci = u - base;
  110.             d edge = max((d)0.0, dist(circles[ci].x, circles[ci].y, bx, by) - circles[ci].r);
  111.             if (dists[e] > cur + edge) {
  112.                 dists[e] = cur + edge;
  113.                 q.push(make_pair(dists[e], e));
  114.             }
  115.             for (int j = 0; j < n; ++j) {
  116.                 if (j == ci) continue;
  117.                 d dij = dist(circles[ci].x, circles[ci].y, circles[j].x, circles[j].y);
  118.                 d edge = max((d)0.0, dij - circles[ci].r - circles[j].r);
  119.                 if (dij <= circles[ci].r + circles[j].r + 1e-9) edge = 0.0;
  120.                 int v = base + j;
  121.                 if (dists[v] > cur + edge) {
  122.                     dists[v] = cur + edge;
  123.                     q.push(make_pair(dists[v], v));
  124.                 }
  125.             }
  126.         }
  127.     }
  128.  
  129.     return (int)floor(dists[e]);
  130. }
  131.  
  132. int main() {
  133.     vector<int> a(2), b(2);
  134.     cin >> a[0] >> a[1];
  135.     cin >> b[0] >> b[1];
  136.  
  137.     int n;
  138.     cin >> n;
  139.     vector<vector<int>> v(n, vector<int>(3, 0));
  140.  
  141.     for (int i = 0; i < n; i++) {
  142.         cin >> v[i][0] >> v[i][1] >> v[i][2];
  143.     }
  144.  
  145.     int ans = minDistance(a, b, v);
  146.     cout << ans << endl;
  147. }
  148.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement