QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#167041#6871. TurretPPP#AC ✓2972ms3676kbC++177.5kb2023-09-06 23:48:392023-09-06 23:48:40

Judging History

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

  • [2023-09-06 23:48:40]
  • 评测
  • 测评结果:AC
  • 用时:2972ms
  • 内存:3676kb
  • [2023-09-06 23:48:39]
  • 提交

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