QOJ.ac

QOJ

IDSubmission IDProblemHackerOwnerResultSubmit timeJudge time
#953#635663#9458. Triangulationhos_lyricucup-team4435Failed.2024-10-13 16:06:022024-10-13 16:06:02

Details

Extra Test:

Invalid Input

input:

70
18
862483 71849
250768 41909
431141 439685
485976 19747
901844 726620
586459 23369
984550 367693
783903 369385
587698 272505
241045 957317
863491 945419
13288 860966
499743 971134
447555 430818
3475 610084
123691 83109
453248 388769
237082 39949
225286 797387 751042 987849 525693 384726 521046 22...

output:


result:

FAIL w[1][1] must equal to 0

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;
}