QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#175642#6570. Who Watches the Watchmen?SolitaryDream#WA 1ms3788kbC++146.2kb2023-09-10 20:57:332023-09-10 20:57:34

Judging History

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

  • [2023-09-10 20:57:34]
  • 评测
  • 测评结果:WA
  • 用时:1ms
  • 内存:3788kb
  • [2023-09-10 20:57:33]
  • 提交

answer

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 505;
struct P3 {
    int x, y, z;
};
inline int Dot(P3 u, P3 v) {
    return u.x * v.x + u.y * v.y + u.z * v.z;
}
inline __int128 Dot128(P3 u, P3 v) {
    return (__int128)u.x * v.x + (__int128)u.y * v.y + (__int128)u.z * v.z;
}
inline P3 Det(P3 u, P3 v) {
    return {u.y * v.z - u.z * v.y,
            u.z * v.x - u.x * v.z,
            u.x * v.y - u.y * v.x};
}
inline P3 operator-(P3 u, P3 v) { return {u.x - v.x, u.y - v.y, u.z - v.z}; }
inline P3 operator+(P3 u, P3 v) { return {u.x + v.x, u.y + v.y, u.z + v.z}; }
inline P3 Neg(P3 u) { return {-u.x, -u.y, -u.z}; }
inline int Len2(P3 u) { return Dot(u, u); }
struct Ray {
    P3 o;
    P3 d;
};
inline bool PointOnRay(P3 a, Ray r) {
    __int128 len2 = Dot(a - r.o, r.d);
    if (len2 < 0) return 0;
    len2 *= len2;
    return len2 == (__int128)Len2(a - r.o) * Len2(r.d);
}
inline bool PointOnSeg(P3 a, P3 u, P3 v) {
    return PointOnRay(a, {u, v - u}) && PointOnRay(a, {v, u - v});
}
namespace KM {
    const int NOT = -1e9;
    const int INF = 1e9;
    int lk[N], pre[N], lx[N], ly[N], slk[N];
    int w[N][N], ans;
    bool vy[N];
    inline void Solve(vector<Ray> pts) {
        int n = pts.size();
        pts.insert(pts.begin(), Ray());
        for (int i = 0; i <= n; ++i)
            for (int j = 0; j <= n; ++j)
                w[i][j] = NOT;
        for (int i = 1; i <= n; ++i) 
            for (int j = 1; j <= n; ++j) if (i != j) {
                int valid = 1;
                for (int k = 1; k <= n; ++k) if (k != i && k != j) {
                    if (PointOnSeg(pts[k].o, pts[i].o, pts[j].o)) { valid = 0; break; }
                }
                if (valid) {
                    int cost = -1;
                    if (PointOnRay(pts[j].o, pts[i])) cost = 0;
                    w[i][j] = cost;
                }
            }
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= n; ++j)
                lx[i] = max(lx[i], w[i][j]);
        int py, p, d, x, y;
        for (int i = 1; i <= n;++i) {
            for (int j = 1; j <= n; ++j) slk[j] = INF, vy[j] = 0;
            for (lk[py = 0] = i; lk[py]; py = p) {
                vy[py] = 1; d = INF; x = lk[py];
                for (y = 1; y <= n; ++y) if (!vy[y]) {
                    if (lx[x] + ly[y] - w[x][y] < slk[y]) slk[y] = lx[x] + ly[y] - w[x][y], pre[y] = py;
                    if (slk[y] < d) d = slk[y], p = y;
                }
                for (y = 0; y <= n; ++y) if (vy[y]) lx[lk[y]] -= d, ly[y] += d; else slk[y] -= d;
            }
            for (; py; py = pre[py]) lk[py] = lk[pre[py]];
        }
        int ans = 0;
        for (int i = 1; i <= n; ++i) {
            ans += lx[i] + ly[i];
            if (w[lk[i]][i] == NOT) ans -= NOT;
        }
        printf("%lld\n", -ans);
    }
}
inline __int128 Sqr128(__int128 x) {
    return x * x;
}
bool SameLine(P3 u, P3 v) {
    return (Sqr128(Dot(u, v)) == (__int128)Len2(u) * Len2(v));
}
inline bool Check(P3 a, P3 b, P3 c) {
    P3 ab = Det(a, b);
    P3 bc = Det(b, c);
    P3 ca = Det(c, a);
    if (Dot(ab, c) != 0) return 0;
    return Dot128(ab, bc) >= 0 && Dot128(bc, ca) >= 0;
}
inline void BF(vector<Ray> pts, P3 dir) {
    int n = pts.size();
    pts.insert(pts.begin(), Ray());
    int ans = 1e9;
    for (int del = 1; del <= n; ++del) {
        Ray ip = pts[del];
        pts.erase(pts.begin() + del);
        vector<int> pre(n + 2), suf(n + 2), R(n + 2), L(n + 2); 
        for (int i = 2; i < n; i += 2) {
            pre[i] += 1 - PointOnRay(pts[i - 1].o, pts[i]);
            pre[i] += 1 - PointOnRay(pts[i].o, pts[i - 1]);
            pre[i] += pre[i - 2];
        }
        for (int i = n - 2; i >= 1; i -= 2) {
            suf[i] += 1 - PointOnRay(pts[i + 1].o, pts[i]);
            suf[i] += 1 - PointOnRay(pts[i].o, pts[i + 1]);
            suf[i] += suf[i + 2];
        }
        for (int i = 1; i < n; ++i) {
            R[i] = R[i - 1] + PointOnRay(pts[i + 1].o, pts[i]);
        }
        for (int i = n - 1; i; --i) {
            L[i] = L[i + 1] + PointOnRay(pts[i - 1].o, pts[i]);
        }
        for (int i = 1; i < n; i += 2)
            for (int j = n - 1; j >= i; j -= 2) {
                int cur = pre[i - 1] + suf[j + 1];
                // all direct right 
                {
                    int val = cur + R[j - 1] - R[i - 1];
                    bool p1 = SameLine(pts[j].d, dir), p2 = SameLine(ip.d, dir);
                    if (p1 && p2) { val += 2; }
                    else if (!p1 && !p2) { val += 1 - Check(dir, pts[j].d, ip.d); }
                    else val += 1;
                    // printf("Right %lld %lld %lld   %lld (%d %d)\n", del, i, j, val, p1, p2);
                    ans = min(ans, val);
                }
                {
                    int val = cur + L[i + 1] - L[j + 1];
                    bool p1 = SameLine(pts[j].d, dir), p2 = SameLine(ip.d, dir);
                    if (p1 && p2) { val += 2; }
                    else if (!p1 && !p2) { val += 1 - Check(Neg(dir), pts[i].d, ip.d); }
                    else val += 1;
                    // printf("Left %lld %lld %lld   %lld (%d %d)\n", del, i, j, val, p1, p2);
                    ans = min(ans, val);
                }
            }
        pts.insert(pts.begin() + del, ip);
    }
    printf("%lld\n", 1000 + ans);
}
signed main() {
    int n;
    scanf("%lld", &n);
    vector<Ray> pts(n);
    for (int i = 0; i < n; ++i) {
        scanf("%lld%lld%lld", &pts[i].o.x, &pts[i].o.y, &pts[i].o.z);
        scanf("%lld%lld%lld", &pts[i].d.x, &pts[i].d.y, &pts[i].d.z);
    }
    if (n == 1) { puts("-1"); return 0; }
    P3 dir = pts[1].o - pts[0].o, ori = pts[0].o;
    sort(pts.begin(), pts.end(), [&](Ray u, Ray v) {
        return Dot(u.o - ori, dir) < Dot(v.o - ori, dir);
    });
    ori = pts[0].o;
    bool same_line = 1;
    for (int i = 1; i < n; ++i) if (!PointOnRay(pts[i].o, {ori, dir})) { same_line = 0; break; }
    if (same_line && (n & 1)) {
        // need 1000
        // puts("Spe!");
        BF(pts, dir);
    } else {
        // no need 1000
        KM::Solve(pts);
    }
    return 0;
}

詳細信息

Test #1:

score: 100
Accepted
time: 1ms
memory: 3736kb

input:

7
0 0 0 1 0 0
1 0 0 -1 0 0
2 0 0 1 0 0
3 0 0 1 0 0
4 0 0 1 0 0
5 0 0 1 0 0
6 0 0 -1 0 0

output:

1002

result:

ok single line: '1002'

Test #2:

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

input:

4
66 45 10 73 39 36
95 14 26 47 84 59
14 66 89 89 36 78
16 27 94 79 24 24

output:

4

result:

ok single line: '4'

Test #3:

score: -100
Wrong Answer
time: 0ms
memory: 3788kb

input:

3
0 0 0 1 0 0
1 1 1 1 0 0
2 2 2 1 0 0

output:

1000

result:

wrong answer 1st lines differ - expected: '1002', found: '1000'