QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#175617 | #6570. Who Watches the Watchmen? | SolitaryDream# | RE | 0ms | 0kb | C++14 | 5.8kb | 2023-09-10 20:43:55 | 2023-09-10 20:43:55 |
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 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 Dot(ab, bc) >= 0 && Dot(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;
ans = min(ans, val);
}
{
int val = cur + L[j] - L[i];
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;
ans = min(ans, val);
}
}
}
printf("%lld\n", 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
BF(pts, dir);
} else {
// no need 1000
KM::Solve(pts);
}
return 0;
}
详细
Test #1:
score: 0
Runtime Error
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