Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <iomanip>
- #include <cmath>
- #include <algorithm>
- #include <vector>
- using namespace std;
- struct point {
- double x, y;
- long long len() {
- long long X = x;
- long long Y = y;
- return X * X + Y * Y;
- }
- void normalize() {
- double opr = sqrt(len());
- x /= opr, y /= opr;
- }
- };
- long long operator * (point& a, point& b) {
- long long x1 = a.x;
- long long y1 = a.y;
- long long x2 = b.x;
- long long y2 = b.y;
- return x1 * y2 - x2 * y1;
- }
- long long operator ^ (point &a, point& b) {
- long long x1 = a.x;
- long long y1 = a.y;
- long long x2 = b.x;
- long long y2 = b.y;
- return x1 * x2 + y1 * y2;
- }
- point operator - (point &a, point &b) {
- return {a.x - b.x, a.y - b.y};
- }
- point operator + (point &a, point &b) {
- return {a.x + b.x, a.y + b.y};
- }
- const int MAXN = 550;
- point p[MAXN][MAXN];
- point pneg[MAXN][MAXN];
- point vcs[MAXN][MAXN];
- point negvcs[MAXN][MAXN];
- point bst[MAXN];
- point bstneg[MAXN];
- int szs[MAXN];
- double d[MAXN][MAXN];
- inline bool cmp1(point &a, point &b) {
- if (a.x != b.x)
- return a.x < b.x;
- return a.y < b.y;
- }
- inline int get_qua(point &a) {
- if (a.x >= 0 && a.y >= 0) {
- return 2;
- }
- if (a.x < 0 && a.y >= 0) {
- return 3;
- }
- if (a.x <= 0 && a.y < 0) {
- return 4;
- }
- return 1;
- }
- inline bool cmp2(point &a, point &b) {
- int fi = get_qua(a), se = get_qua(b);
- if (fi != se)
- return fi < se;
- if ((a * b) == 0) {
- return a.len() < b.len();
- }
- return (a * b) > 0;
- }
- vector <point> get_mink(vector <point>&a, vector<point> &b) {
- vector <point> rx;
- for (int i = 1; i < a.size(); ++i) rx.push_back(a[i] - a[i - 1]);
- for (int i = 1; i < b.size(); ++i) rx.push_back(b[i] - b[i - 1]);
- rx.push_back(a[0] - a.back());
- rx.push_back(b[0] - b.back());
- vector <point> ret_sum;
- ret_sum.push_back(*min_element(a.begin(), a.end(), cmp1) + *min_element(b.begin(), b.end(), cmp1));
- sort(rx.begin(), rx.end(), cmp2);
- for (auto i : rx) {
- ret_sum.push_back(ret_sum.back() + i);
- }
- return ret_sum;
- }
- struct segment {
- point begin, end;
- };
- struct line {
- double A, B, C;
- };
- line toline(point& a, point& b) {
- line t;
- t.A = a.y - b.y;
- t.B = b.x - a.x;
- t.C = a.x * b.y - b.x * a.y;
- return t;
- }
- double get_dist(point& a, line& b) {
- double opr = sqrt(b.A * b.A + b.B * b.B);
- b.A /= opr, b.B /= opr, b.C /= opr;
- return fabs(b.A * a.x + b.B * a.y + b.C);
- }
- bool operator==(point& a, point& b) {
- return a.x == b.x && a.y == b.y;
- }
- double get_dist(segment &a, point& b) {
- auto zn = (a.begin - a.end) ^ (b - a.end);
- auto zn2 = (a.end - a.begin) ^ (b - a.begin);
- if (zn >= 0 && zn2 >= 0) {
- return get_dist(b, toline(a.begin, a.end));
- }
- else {
- return sqrt(min((b - a.begin).len(), (b - a.end).len()));
- }
- }
- double get_dist(int id1, int id2) {
- point pred = bst[id1] + bstneg[id2];
- double ret = 1e18;
- int i1 = 0, i2 = 0;
- for (int k = 0; k < szs[id1] + szs[id2]; ++k) {
- if (i1 == szs[id1]) {
- point cur = pred + negvcs[id2][i2++];
- ret = min(ret, get_dist(segment{pred, cur}, point{0, 0}));
- pred = cur;
- }
- else if (i2 == szs[id2]) {
- point cur = pred + vcs[id1][i1++];
- ret = min(ret, get_dist(segment {pred, cur}, point {0, 0}));
- pred = cur;
- }
- else {
- if (cmp2(vcs[id1][i1], negvcs[id2][i2])) {
- point cur = pred + vcs[id1][i1++];
- ret = min(ret, get_dist(segment {pred, cur}, point {0, 0}));
- pred = cur;
- }
- else {
- point cur = pred + negvcs[id2][i2++];
- ret = min(ret, get_dist(segment {pred, cur}, point {0, 0}));
- pred = cur;
- }
- }
- }
- return ret;
- }
- void make(int n) {
- for (int i = 0; i < n; ++i) {
- d[i][i] = 0;
- for (int j = i + 1; j < n; ++j) {
- d[i][j] = d[j][i] = get_dist(i, j);
- }
- }
- }
- void floyd(int n) {
- for (int k = 0; k < n; ++k) {
- for (int i = 0; i < n; ++i) {
- for (int j = 0; j < n; ++j) {
- d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
- }
- }
- }
- }
- int main() {
- ios::sync_with_stdio(false);
- cin.tie(0);
- int n, a, b;
- cin >> n >> a >> b;
- --a, --b;
- for (int i = 0; i < n; ++i) {
- int sz;
- cin >> sz;
- szs[i] = sz;
- for (int j = 0; j < sz; ++j) {
- cin >> p[i][j].x >> p[i][j].y;
- pneg[i][j].x = -p[i][j].x;
- pneg[i][j].y = -p[i][j].y;
- }
- for (int j = 0; j + 1 < sz; ++j) {
- vcs[i][j] = p[i][j + 1] - p[i][j];
- }
- vcs[i][sz - 1] = p[i][0] - p[i][sz - 1];
- sort(vcs[i], vcs[i] + sz, cmp2);
- for (int j = 0; j + 1 < sz; ++j) {
- negvcs[i][j] = pneg[i][j + 1] - pneg[i][j];
- }
- negvcs[i][sz - 1] = pneg[i][0] - pneg[i][sz - 1];
- sort(negvcs[i], negvcs[i] + sz, cmp2);
- bst[i] = *min_element(p[i], p[i] + sz, cmp1);
- bstneg[i] = *min_element(pneg[i], pneg[i] + sz, cmp1);
- }
- make(n);
- floyd(n);
- cout << fixed << setprecision(10);
- cout << d[a][b];
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement