QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#167041 | #6871. Turret | PPP# | AC ✓ | 2972ms | 3676kb | C++17 | 7.5kb | 2023-09-06 23:48:39 | 2023-09-06 23:48:40 |
Judging History
answer
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif
#pragma GCC optimize("O3")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
const int mod = 998244353;
int mult(int a, int b) {
return (1LL * a * b) % mod;
}
int sub(int a, int b) {
int s = a - b;
if (s < 0) s += mod;
return s;
}
int pw(int a, int b) {
if (b == 0) return 1;
if (b & 1) return mult(a, pw(a, b - 1));
int res = pw(a, b / 2);
return mult(res, res);
}
int sum(int a, int b) {
int s = a + b;
if (s >= mod) s -= mod;
return s;
}
int n, m;
const int maxN = 22;
int x[maxN][maxN];
int y[maxN][maxN];
vector<pair<ll, ll>> poly[maxN];
bool can[(1 << 15) + 2];
int dp[(1 << 15) + 2];
mt19937 rnd(228);
void solve() {
cin >> n;
// n = 15;
vector<pair<ll, ll>> cands;
vector<pair<ll, ll>> good;
for (int i = 0; i < n; i++) {
int sz = 13;
cin >> sz;
poly[i].resize(sz);
for (auto &it: poly[i]) {
cin >> it.first >> it.second;
}
good.emplace_back(poly[i][0]);
}
// cands.emplace_back(0, 0);
good.emplace_back(0, 0);
// cands.emplace_back(10000, 10000);
good.emplace_back(10000, 10000);
// cands.emplace_back(0, 10000);
good.emplace_back(0, 10000);
// cands.emplace_back(10000, 0);
good.emplace_back(10000, 0);
sort(good.begin(), good.end());
good.erase(unique(good.begin(), good.end()), good.end());
vector<tuple<ll, ll, ll>> line;
auto get_line = [&](ll x1, ll y1, ll x2, ll y2) {
ll A = y2 - y1;
ll B = x1 - x2;
ll C = -x1 * A - y1 * B;
return make_tuple(A, B, C);
};
auto get_line2 = [&](pair<ll, ll> &T1, pair<ll, ll> &T2) {
return get_line(T1.first, T1.second, T2.first, T2.second);
};
for (int i = 0; i < good.size(); i++) {
for (int j = i + 1; j < good.size(); j++) {
if (good[i] == good[j]) continue;
// if (A < 0 || (A == 0 && B < 0)) {
// A *= -1;
// B *= -1;
// C *= -1;
// }
// ll D = __gcd(llabs(A), __gcd(llabs(B), llabs(C)));
// A /= D;
// B /= D;
// C /= D;
line.push_back(get_line2(good[i], good[j]));
}
}
for (int i = 0; i < n; i++) {
line.push_back(get_line2(poly[i][0], poly[i][1]));
line.push_back(get_line2(poly[i][0], poly[i].back()));
for (int j = 0; j < n; j++) {
if (i == j) continue;
int mn_ind = 0;
int mx_ind = 0;
for (int k = 1; k < poly[j].size(); k++) {
auto l1 = get_line2(poly[i][0], poly[j][mn_ind]);
if (get<0>(l1) * poly[j][k].first + get<1>(l1) * poly[j][k].second + get<2>(l1) > 0) {
mn_ind = k;
}
l1 = get_line2(poly[i][0], poly[j][mx_ind]);
if (get<0>(l1) * poly[j][k].first + get<1>(l1) * poly[j][k].second + get<2>(l1) < 0) {
mx_ind = k;
}
}
line.push_back(get_line2(poly[i][0], poly[j][mn_ind]));
line.push_back(get_line2(poly[i][0], poly[j][mx_ind]));
}
}
auto det = [&](ll a11, ll a12, ll a21, ll a22) {
return a11 * a22 - a21 * a12;
};
const ld eps = 1e-12;
auto eq = [&](ld a, ld b) {
return fabsl(a - b) < eps;
};
for (int z = 0; z < (1 << n); z++) can[z] = false;
sort(line.begin(), line.end());
line.erase(unique(line.begin(), line.end()), line.end());
for (auto &it: line) {
for (auto &jit: line) {
if (it >= jit) continue;
ll A1 = get<0>(it);
ll B1 = get<1>(it);
ll C1 = get<2>(it);
ll A2 = get<0>(jit);
ll B2 = get<1>(jit);
ll C2 = get<2>(jit);
ll D = det(A1, B1, A2, B2);
if (D == 0) continue;
ll D1 = det(-C1, B1, -C2, B2);
ll D2 = det(A1, -C1, A2, -C2);
if (D < 0) {
D *= -1;
D1 *= -1;
D2 *= -1;
}
if (D1 < 0 || D2 < 0 || D1 > 10000 * D || D2 > 10000 * D) continue;
ld x = (ld) D1 / D;
ld y = (ld) D2 / D;
int msk = 0;
for (int t = 0; t < n; t++) {
bool good = true;
for (int j = 0; j < n; j++) {
ld dx = (poly[t][0].first - x);
ld dy = (poly[t][0].second - y);
if (fabsl(dx) < eps && fabsl(dy) < eps) {
break;
}
ld L = 0;
ld R = 1;
bool has_equal = false;
for (int f = 0; f < poly[j].size(); f++) {
auto t1 = poly[j][f];
auto t2 = poly[j][(f + 1) % poly[j].size()];
ll A = t2.second - t1.second;
ll B = t1.first - t2.first;
ll C = -A * t1.first - B * t1.second;
A *= -1;
B *= -1;
C *= -1;
auto t3 = poly[j][(f + 2) % poly[j].size()];
assert(t3.first * A + t3.second * B + C > 0);
ld coef = A * dx + B * dy;
ld val = A * x + B * y + C;
//coef * t + val >= 0
//val < 0
if (fabsl(coef) < eps) {
if (val < eps) {
has_equal = true;
break;
}
} else {
if (coef > eps) {
L = max(L, -val / coef);
} else {
R = min(R, -val / coef);
}
}
if (L + eps > R) break;
}
if (L + eps < R && !has_equal) {
good = false;
break;
}
}
if (good) {
msk |= (1 << t);
}
}
can[msk] = true;
}
}
for (int bit = 0; bit < n; bit++) {
for (int mask = 0; mask < (1 << n); mask++) {
if (mask & (1 << bit)) {
can[mask ^ (1 << bit)] |= can[mask];
}
}
}
const int INF = 1e9;
for (int mask = 0; mask < (1 << n); mask++) {
if (can[mask]) {
dp[mask] = 1;
} else {
dp[mask] = INF;
}
}
for (int mask = 0; mask < (1 << n); mask++) {
if (dp[mask] == INF) continue;
int sb = ((1 << n) - 1) ^ mask;
while (true) {
if (can[sb]) {
dp[mask | sb] = min(dp[mask | sb], dp[mask] + 1);
}
if (sb == 0) break;
sb = (((1 << n) - 1) ^ mask) & (sb - 1);
}
}
cout << dp[(1 << n) - 1] << '\n';
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
#ifdef DEBUG
freopen("input.txt", "r", stdin);
#endif
int tst = 1;
cin >> tst;
while (tst--) {
solve();
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 2972ms
memory: 3676kb
input:
10 5 8 3640 2337 5128 1817 5228 1863 5188 2765 5034 3655 4384 3715 3802 3251 3682 2579 7 2343 5705 799 5745 579 4193 1179 3837 1513 3787 2221 3991 2331 4137 7 5734 6064 6136 5810 7396 5930 7588 6328 7534 7074 6512 7708 5726 7376 8 9256 2017 8606 2473 8032 2291 7374 1869 7328 1605 7462 1123 8056 1063...
output:
2 1 2 2 3 3 5 4 6 5
result:
ok 10 lines