QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#485815#5479. Traveling Salesperson in an IslandenwaskWA 22ms4084kbC++176.0kb2024-07-21 09:46:532024-07-21 09:46:53

Judging History

你现在查看的是最新测评结果

  • [2024-07-21 09:46:53]
  • 评测
  • 测评结果:WA
  • 用时:22ms
  • 内存:4084kb
  • [2024-07-21 09:46:53]
  • 提交

answer

#include <bits/stdc++.h>
using namespace std;

#define rep(i, a, b) for (int i = a; i < (b); ++i)
#define all(x) begin(x), end(x)
#define sz(x) (int) (x).size()
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;

template<class T>
int sgn(T x) { return (x > 0) - (x < 0); }
template<class T>
struct Point {
    typedef Point P;
    T x, y;
    explicit Point(T x = 0, T y = 0) : x(x), y(y) {}
    bool operator<(P p) const { return tie(x, y) < tie(p.x, p.y); }
    bool operator==(P p) const { return (p - *this).dist2() < 1e-8; }
    P operator+(P p) const { return P(x + p.x, y + p.y); }
    P operator-(P p) const { return P(x - p.x, y - p.y); }
    P operator*(T d) const { return P(x * d, y * d); }
    P operator/(T d) const { return P(x / d, y / d); }
    T dot(P p) const { return x * p.x + y * p.y; }
    T cross(P p) const { return x * p.y - y * p.x; }
    T cross(P a, P b) const { return (a - *this).cross(b - *this); }
    T dist2() const { return x * x + y * y; }
    ld dist() const { return sqrtl((ld) dist2()); }
    // angle to x-axis in interval [-pi, pi]
    double angle() const { return atan2(y, x); }
    P unit() const { return *this / dist(); } // makes dist()=1
    P perp() const { return P(-y, x); }       // rotates +90 degrees
    P normal() const { return perp().unit(); }
    // returns point rotated 'a' radians ccw around the origin
    P rotate(double a) const {
        return P(x * cos(a) - y * sin(a), x * sin(a) + y * cos(a));
    }
    friend ostream &operator<<(ostream &os, P p) {
        return os << "(" << p.x << "," << p.y << ")";
    }
};
const ld inf = 1e18;
const ld eps = 1e-8;
typedef Point<ld> P;

template<class P>
int sideOf(P s, P e, P p) {
    auto cp = s.cross(e, p);
    return (cp > 0) - (cp < 0);
}

template<class P>
bool doSegInter(P s1, P e1, P s2, P e2) {
    return sideOf(s1, e1, s2) != sideOf(s1, e1, e2) && sideOf(s2, e2, s1) != sideOf(s2, e2, e1);
}

// 0 = no intersection, 1 = segments intersect, -1 = coincide or share an endpoint
int segInter(P a, P b, P c, P d) {
    auto oa = c.cross(d, a), ob = c.cross(d, b),
         oc = a.cross(b, c), od = a.cross(b, d);

    if (sgn(oa) * sgn(ob) > 0 || sgn(oc) * sgn(od) > 0) return 0; // no intersection
    if (sgn(oa) * sgn(ob) < 0 && sgn(oc) * sgn(od) < 0) return 1; // intersection

    return -1; // coincide or share an endpoint
}

template<class P>
bool onSegment(P s, P e, P p) {
    return abs(s.cross(e, p)) < eps && (s - p).dot(e - p) < eps;
}

template<class P>
int inPoly(vector<P> poly, P p) {
    bool good = false;
    int n = sz(poly);
    auto crosses = [](P s, P e, P p) {
        return ((e.y >= p.y) - (s.y >= p.y)) * p.cross(s, e) > 0;
    };
    for (int i = 0; i < n; i++) {
        if (onSegment(poly[i], poly[(i + 1) % n], p)) return 2;
        good ^= crosses(poly[i], poly[(i + 1) % n], p);
    }
    return good;
}

// #include "geo.h"
void solve() {
    int n, m;
    cin >> n >> m;

    vector<P> pol(n), pts(m), old_pts(n + m), all_pts;
    for (auto &[x, y] : pol) cin >> x >> y;
    for (auto &[x, y] : pts) cin >> x >> y;
    copy(all(pol), begin(old_pts));
    copy(all(pts), begin(old_pts) + n);

    // sort everything
    rep(i, 0, n) {
        P u = pol[i], v = pol[(i + 1) % n];
        vector<P> lin{u, v};
        rep(j, 0, m) {
            P p = pts[j];
            if (onSegment(u, v, p)) lin.push_back(p);
        }
        old_pts.erase(
                remove_if(all(old_pts), [&](P p) {
                    return count(all(lin), p);
                }),
                end(old_pts));
        sort(all(lin), [&](P a, P b) {
            return (a - u).dist2() < (b - u).dist2();
        });
        all_pts.insert(end(all_pts), all(lin));
    }
    all_pts.erase(unique(all(all_pts)), end(all_pts));
    int tot = sz(all_pts);

    // GD_INIT("vis.html");
    // rep(i, 0, tot) {
    //     P u = all_pts[i], v = all_pts[(i + 1) % tot];
    //     if (count(all(pts), u)) GD_POINT(u.x, u.y, "black");
    //     GD_SEGMENT(u.x, u.y, v.x, v.y, "black");
    // }
    // GD_PAUSE();

    vector<vector<pair<int, ld>>> adj(tot);
    auto do_thing = [&](int i, int j) -> bool {
        P a = all_pts[i], b = all_pts[j];

        // check if we intersect any edges (that are not adjacent to a or b)
        rep(k, 0, n) {
            if (k == i || k == j || (k + 1) % n == i || (k + 1) % n == j) continue;
            P c = pol[k], d = pol[(k + 1) % n];

            // check for intersection
            int inter = segInter(a, b, c, d);
            if (inter > 0) return false;
        }

        // check if the edge is inside the polygon
        P m = (a + b) / 2.l;
        if (!inPoly(pol, m)) return false;

        // GD_SEGMENT(a.x, a.y, b.x, b.y, "green");
        ld d = (a - b).dist();
        adj[i].emplace_back(j, d);
        adj[j].emplace_back(i, d);
        return true;
    };
    rep(i, 0, tot) {
        rep(j, i + 1, tot) {
            do_thing(i, j);
        }
    }


    vector<vector<ld>> dist(tot, vector<ld>(tot, 1e18));
    rep(i, 0, tot) dist[i][i] = 0;
    rep(i, 0, tot) for (auto [j, d] : adj[i]) dist[i][j] = min(dist[i][j], d);
    rep(h, 0, tot) rep(i, 0, tot) rep(j, 0, tot)
            dist[i][j] = min(
                    dist[i][j],
                    dist[i][h] + dist[h][j]);

    // // print dist
    // cout << "\ndist:\n";
    // rep(i, 0, k) {
    //     cout << i << ": {\n";
    //     rep(j, 0, k) cout << "\t-> " << j << " = " << dist[i][j] << "\n";
    //     cout << "}\n";
    // }

    vector<pair<int, P>> ord;
    rep(i, 0, tot) if (count(all(pts), all_pts[i])) ord.emplace_back(i, all_pts[i]);

    // GD_PAUSE();
    ld res = 0;
    rep(i, 0, m) {
        int u = ord[i].first, v = ord[(i + 1) % m].first;
        res += dist[u][v];
        // GD_SEGMENT(all_pts[u].x, all_pts[u].y, all_pts[v].x, all_pts[v].y, "red bold");
    }
    // GD_CIRCLE(ord[0].second.x, ord[0].second.y, 10, "red bold");
    cout << setprecision(10) << fixed << res << '\n';
}

int main() {
    cin.tie(0)->sync_with_stdio(0);
    cin.exceptions(cin.failbit);

    int t = 1;
    // cin >> t;
    while (t--) solve();

    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 3988kb

input:

4 4
0 0
2 0
2 2
0 2
1 0
1 2
2 1
0 1

output:

5.6568542495

result:

ok found '5.6568542', expected '5.6568542', error '0.0000000'

Test #2:

score: 0
Accepted
time: 0ms
memory: 4084kb

input:

8 2
0 0
4 0
4 4
0 4
0 3
3 3
3 1
0 1
0 0
0 4

output:

16.6491106407

result:

ok found '16.6491106', expected '16.6491106', error '0.0000000'

Test #3:

score: 0
Accepted
time: 0ms
memory: 3864kb

input:

4 4
0 0
2 0
2 2
0 2
1 0
2 1
1 2
0 1

output:

5.6568542495

result:

ok found '5.6568542', expected '5.6568542', error '0.0000000'

Test #4:

score: 0
Accepted
time: 0ms
memory: 3808kb

input:

8 2
0 0
4 0
4 4
0 4
0 3
3 3
3 1
0 1
0 0
0 4

output:

16.6491106407

result:

ok found '16.6491106', expected '16.6491106', error '0.0000000'

Test #5:

score: -100
Wrong Answer
time: 22ms
memory: 4084kb

input:

76 98
268 97
299 202
133 205
110 251
384 226
332 198
532 241
448 83
268 82
543 62
873 93
387 317
905 90
945 132
827 335
983 222
919 534
945 264
910 287
789 705
837 176
793 563
777 665
782 345
746 315
715 315
810 161
369 599
278 671
641 423
703 344
753 619
672 402
596 709
161 701
216 857
325 942
135 ...

output:

14637.0741178637

result:

wrong answer 1st numbers differ - expected: '14645.5751139', found: '14637.0741179', error = '0.0005804'