QOJ.ac

QOJ

IDSubmission IDProblemHackerOwnerResultSubmit timeJudge time
#955#635663#9458. Triangulationhos_lyricucup-team4435Failed.2024-10-13 16:09:122024-10-13 16:09:13

Details

Extra Test:

Standard Program Time Limit Exceeded

input:

70
18
523990 661228
542094 867454
715348 957693
724847 921955
185285 504782
340889 164109
548808 628313
528132 176875
403401 165509
733176 362440
62653 306280
841647 146408
169951 295342
186442 591918
405268 31651
207390 724432
622724 775650
495011 800641
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 ...

output:


result:


IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#635663#9458. Triangulationucup-team4435#TL 85ms79068kbC++2011.3kb2024-10-12 20:32:192024-10-13 18:02:34

answer

#include "bits/stdc++.h"

#ifdef LOCAL
    #include "debug.h"
#else
    #define dbg(...)
    #define dprint(...)
    #define debug if constexpr (false)
    #define draw_tree(...)
    #define draw_array(...)
#endif // LOCAL

#define rep(i, n) for (int i = 0; i < (n); ++i)
#define rep1(i, n) for (int i = 1; i < (n); ++i)
#define rep1n(i, n) for (int i = 1; i <= (n); ++i)
#define repr(i, n) for (int i = (n) - 1; i >= 0; --i)
#define pb push_back
#define eb emplace_back
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define each(x, a) for (auto &x : a)
#define ar array
#define vec vector
#define range(i, n) rep(i, n)

using namespace std;

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using str = string;
using pi = pair<int, int>;
using pl = pair<ll, ll>;

using vi = vector<int>;
using vl = vector<ll>;
using vpi = vector<pair<int, int>>;
using vvi = vector<vi>;

int Bit(int mask, int b) { return (mask >> b) & 1; }

template<class T>
bool ckmin(T &a, const T &b) {
    if (b < a) {
        a = b;
        return true;
    }
    return false;
}

template<class T>
bool ckmax(T &a, const T &b) {
    if (b > a) {
        a = b;
        return true;
    }
    return false;
}

// [l, r)
template<typename T, typename F>
T FindFirstTrue(T l, T r, const F &predicat) {
    --l;
    while (r - l > 1) {
        T mid = l + (r - l) / 2;
        if (predicat(mid)) {
            r = mid;
        } else {
            l = mid;
        }
    }
    return r;
}


template<typename T, typename F>
T FindLastFalse(T l, T r, const F &predicat) {
    return FindFirstTrue(l, r, predicat) - 1;
}


const ll INF = 2e18;
const int INFi = 2e9;

bool Equal(ll A, ll B) {
    return A == B;
}

bool Less(ll A, ll B) {
    return A < B;
}

bool Greater(ll A, ll B) {
    return A > B;
}

bool LessOrEqual(ll A, ll B) {
    return A <= B;
}

bool GreaterOrEqual(ll A, ll B) {
    return A >= B;
}

const ld EPS = 1e-9;

bool Equal(ld A, ld B) {
    return abs(A - B) < EPS;
}

bool Less(ld A, ld B) {
    return A + EPS < B;
}

bool Greater(ld A, ld B) {
    return A > B + EPS;
}

bool LessOrEqual(ld A, ld B) {
    return A <= B + EPS;
}

bool GreaterOrEqual(ld A, ld B) {
    return A + EPS >= B;
}

template<typename T, typename Q>
bool LessOrEqual(T A, Q B) {
    using C = std::common_type_t<T, Q>;
    return LessOrEqual(static_cast<C>(A), static_cast<C>(B));
}

template<typename T, typename Q>
bool Equal(T A, Q B) {
    using C = std::common_type_t<T, Q>;
    return Equal(static_cast<C>(A), static_cast<C>(B));
}

template<typename T, typename Q>
bool Less(T A, Q B) {
    using C = std::common_type_t<T, Q>;
    return Less(static_cast<C>(A), static_cast<C>(B));
}

template<typename T, typename Q>
bool Greater(T A, Q B) {
    using C = std::common_type_t<T, Q>;
    return Greater(static_cast<C>(A), static_cast<C>(B));
}

template<typename T, typename Q>
bool GreaterOrEqual(T A, Q B) {
    using C = std::common_type_t<T, Q>;
    return GreaterOrEqual(static_cast<C>(A), static_cast<C>(B));
}

template<typename T>
ll sgn(T x) {
    if (Equal(x, 0)) return 0;
    return Less(x, 0) ? -1 : 1;
}


template<typename T>
struct Point {
    T x;
    T y;

    Point(T x_ = 0, T y_ = 0) : x(x_), y(y_) {}

    template<typename Q>
    Point(const Point<Q> &other) {
        x = static_cast<T>(other.x);
        y = static_cast<T>(other.y);
    }


    template<typename Q>
    Point(Point<Q> &&other) {
        x = static_cast<T>(other.x);
        y = static_cast<T>(other.y);
    }

    template<typename Q>
    Point<std::common_type_t<T, Q>> operator+(const Point<Q> &oth) const {
        return Point{x + oth.x, y + oth.y};
    }

    template<typename Q>
    Point<std::common_type_t<T, Q>> operator-(const Point<Q> &oth) const {
        return {x - oth.x, y - oth.y};
    }

    template<typename Q>
    bool operator==(const Point<Q> &oth) const {
        return x == oth.x && y == oth.y;
    }

    template<typename Q>
    bool operator<(const Point<Q> &oth) const {
        return make_pair(x, y) < make_pair(oth.x, oth.y);
    }

    template<typename Q>
    requires (is_integral_v<Q> || is_floating_point_v<Q>)
    Point<std::common_type_t<Q, T>> operator*(const Q &b) const {
        return {x * b, y * b};
    }


    template<typename Q>
    requires (is_integral_v<Q> || is_floating_point_v<Q>)
    Point<ld> operator/(const Q &b) const {
        return {(ld) x / b, (ld) y / b};
    }

    template<typename Q>
    std::common_type_t<Q, T> operator*(const Point<Q> &oth) const {
        return x * oth.y - y * oth.x;
    }

    template<typename Q>
    std::common_type_t<Q, T> operator%(const Point<Q> &oth) const {
        return x * oth.x + y * oth.y;
    }

    Point &operator+=(const Point &other) {
        x += other.x;
        y += other.y;
        return *this;
    }

    Point &operator-=(const Point &other) {
        x -= other.x;
        y -= other.y;
        return *this;
    }

    friend ostream &operator<<(ostream &stream, const Point &P) {
        stream << P.x << ' ' << P.y;
        return stream;
    }


    friend istream &operator>>(istream &stream, Point &P) {
        stream >> P.x >> P.y;
        return stream;
    }
};

template<typename T>
Point<T> rotateCW(const Point<T> &P) {
    return {P.y, -P.x};
}

template<typename T>
Point<T> rotateCCW(const Point<T> &P) {
    return {-P.y, P.x};
}

template<typename T, typename Q>
bool Equal(const Point<T> &a, const Point<Q> &b) {
    return Equal(a.x, b.x) && Equal(a.y, b.y);
}

template<typename T, typename Q>
bool Less(const Point<T> &a, const Point<Q> &b) {
    if (!Equal(a.x, b.x)) return Less(a.y, b.y);
    return Less(a.y, b.y);
}

template<typename T, typename Q>
bool Greater(const Point<T> &a, const Point<Q> &b) {
    if (!Equal(a.x, b.x)) return Greater(a.y, b.y);
    return Greater(a.y, b.y);
}

template<typename T>
Point<T> operator-(const Point<T> &a) {
    return {-a.x, -a.y};
}


template<typename T>
T len2(const Point<T> &a) {
    return a % a;
}

template<typename T>
ld len(const Point<T> &a) {
    return sqrtl(len2(a));
}

template<typename T, typename Q>
T dist2(const Point<T> &a, const Point<Q> &b) {
    return len2(a - b);
}

template<typename T, typename Q>
ld dist(const Point<T> &a, const Point<Q> &b) {
    return len(a - b);
}

using pt = Point<ll>;

template<typename T, typename U>
bool VComp(const Point<T> &a, const Point<U> &b) {
    bool upA = a.y > 0 || (a.y == 0 && a.x >= 0);
    bool upB = b.y > 0 || (b.y == 0 && b.x >= 0);
    if (upA != upB) return upA;
    auto val = a * b;
    if (val != 0) return val > 0;
    return len2(a) < len2(b);
}

template<typename T, typename U>
bool VCompNoLen(const Point<T> &a, const Point<U> &b) {
    bool upA = a.y > 0 || (a.y == 0 && a.x >= 0);
    bool upB = b.y > 0 || (b.y == 0 && b.x >= 0);
    if (upA != upB) return upA;
    auto val = a * b;
    return val > 0;
}


const int LG = 18;
const int N = 1 << LG;

pair<ll, ll> dp[N][LG];
bool valid[LG][LG][LG];

void add(int i, int j, pair<ll, ll> ways, ll cost) {
    ways.first += cost;
    if (dp[i][j].first < ways.first) return;
    if (dp[i][j].first > ways.first) {
        dp[i][j].first = ways.first;
        dp[i][j].second = 0;
    }
    dp[i][j].second += ways.second;
}

int GetBit(int mask, int b) {
    return (mask >> b) & 1;
}

vector<pt> a;
vector<vl> w;
int n;
vi was;

pair<ll, ll> solve(int mask, int b) {
    if (dp[mask][b].second != -1) return dp[mask][b];
    was.push_back(mask);
    dp[mask][b].second = 0;

    int pr = b - 1;
    int nx = b + 1;
    while (pr >= 0 && !GetBit(mask, pr)) pr--;
    while (nx < n && !GetBit(mask, nx)) nx++;

    if (nx != n) {
        add(mask, b, solve(mask, nx), 0);
        for(int t = b + 1; t < nx; ++t) {
            if (valid[b][t][nx] && (a[nx] - a[b]) * (a[t] - a[b]) > 0) {
                add(mask, b, solve(mask ^ (1 << t), b), w[t][nx] + w[t][b]);
                dbg(mask, b, dp[mask][b], t);
            }
        }
        if (pr != -1) {
            if (valid[pr][b][nx] && (a[b] - a[pr]) * (a[nx] - a[pr]) > 0) {
                add(mask, b, solve(mask ^ (1 << b), pr), w[pr][nx]);
                dbg(mask, b, dp[mask][b], -1);
            }
        }
    }
    dbg(mask, b, dp[mask][b]);
    return dp[mask][b];
}

template<typename T>
bool inside(Point<T> a, Point<T> b, Point<T> c, Point<T> d) {
    auto area = [&](auto v1, auto v2) {
        return abs(v1 * v2);
    };
    return area(b - a, c - a) == area(a - d, b - d) + area(b - d, c - d) + area(c - d, a - d);
}

void solve() {
    cin >> n;
    a.resize(n);
    rep(i, n) cin >> a[i];

    w.assign(n, vl(n));
    rep(i, n) {
        rep(j, n) {
            cin >> w[i][j];
        }
    }

    {
        vi ord(n);
        iota(all(ord), 0);
        sort(all(ord), [&](const int &i, const int &j) { return a[i] < a[j]; });

        vector<pt> b(n);
        rep(i, n) b[i] = a[ord[i]];
        vector<vl> ww(n, vl(n));
        rep(i, n) {
            rep(j, n) {
                ww[i][j] = w[ord[i]][ord[j]];
            }
        }
        swap(a, b);
        swap(w, ww);
    }

    memset(valid, 0, sizeof(valid));
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            for (int k = j + 1; k < n; k++) {
                bool ok = true;
                for (int x = 0; x < n; x++) {
                    if (x == i || x == j || x == k) {
                        continue;
                    }
                    if (inside(a[i], a[j], a[k], a[x])) {
                        ok = false;
                        break;
                    }
                }
                valid[i][j][k] = ok;
            }
        }
    }

    {
        vi stk;
        stk.push_back(0);
        for (int i = 1; i < n; ++i) {
            while (stk.size() >= 2 &&
                   (a[stk[stk.size() - 1]] - a[stk[stk.size() - 2]]) * (a[i] - a[stk[stk.size() - 2]]) > 0) {
                stk.pop_back();
            }
            stk.push_back(i);
        }
        int mask = 0;
        for (auto &i: stk) mask |= (1 << i);
        dp[mask][n - 1] = {0, 1};
        was.push_back(mask);
    }
    {
        vi stk;
        stk.push_back(0);
        for (int i = 1; i < n; ++i) {
            while (stk.size() >= 2 &&
                   (a[stk[stk.size() - 1]] - a[stk[stk.size() - 2]]) * (a[i] - a[stk[stk.size() - 2]]) < 0) {
                stk.pop_back();
            }
            stk.push_back(i);
        }
        int mask = 0;
        for (auto &i: stk) mask |= (1 << i);
        ll res = 0;
        for(int i = 1; i < stk.size(); ++i) res += w[stk[i - 1]][stk[i]];

        auto ans = solve(mask, 0);
        ans.first += res;
        cout << ans.first << ' ' << ans.second << '\n';
    }


    for(auto &mask : was) {
        rep(i, n) dp[mask][i] = {INF, -1};
    }
    was.clear();
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout << setprecision(12) << fixed;
    int t = 1;
    rep(i, N) rep(j, LG) dp[i][j] = {INF, -1};

    cin >> t;
    rep(i, t) {
        solve();
    }
    return 0;
}