QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#638565 | #9458. Triangulation | hos_lyric | TL | 150ms | 78848kb | C++14 | 7.3kb | 2024-10-13 16:14:44 | 2024-10-13 18:03:04 |
Judging History
answer
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
using Int = long long;
template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
#define COLOR(s) ("\x1b[" s "m")
inline int sig(Int r) { return (r < 0) ? -1 : (r > 0) ? +1 : 0; }
inline Int sq(Int r) { return r * r; }
struct Pt {
Int x, y;
Pt() : x(0), y(0) {}
Pt(Int x_, Int y_) : x(x_), y(y_) {}
Pt operator+(const Pt &a) const { return Pt(x + a.x, y + a.y); }
Pt operator-(const Pt &a) const { return Pt(x - a.x, y - a.y); }
Pt operator*(const Pt &a) const { return Pt(x * a.x - y * a.y, x * a.y + y * a.x); }
Pt operator+() const { return Pt(+x, +y); }
Pt operator-() const { return Pt(-x, -y); }
Pt operator*(const Int &k) const { return Pt(x * k, y * k); }
Pt operator/(const Int &k) const { return Pt(x / k, y / k); }
friend Pt operator*(const Int &k, const Pt &a) { return Pt(k * a.x, k * a.y); }
Pt &operator+=(const Pt &a) { x += a.x; y += a.y; return *this; }
Pt &operator-=(const Pt &a) { x -= a.x; y -= a.y; return *this; }
Pt &operator*=(const Pt &a) { return *this = *this * a; }
Pt &operator*=(const Int &k) { x *= k; y *= k; return *this; }
Int abs2() const { return x * x + y * y; }
Int dot(const Pt &a) const { return x * a.x + y * a.y; }
Int det(const Pt &a) const { return x * a.y - y * a.x; }
bool operator==(const Pt &a) const { return (x == a.x && y == a.y); }
bool operator!=(const Pt &a) const { return !(x == a.x && y == a.y); }
bool operator<(const Pt &a) const { return ((x != a.x) ? (x < a.x) : (y < a.y)); }
friend ostream &operator<<(ostream &os, const Pt &a) { os << "(" << a.x << ", " << a.y << ")"; return os; }
};
inline Int tri(const Pt &a, const Pt &b, const Pt &c) { return (b - a).det(c - a); }
constexpr int INF = 1001001001;
int N;
vector<Pt> P;
int W[18][18];
// P: Pt * or vector<Pt>
int sigtri(int u, int v, int w) {
return sig(tri(P[u], P[v], P[w]));
}
vector<int> convexHull(vector<int> us, bool sorted = false) {
const int n = us.size();
if (!sorted) {
sort(us.begin(), us.end(), [&](int u, int v) -> bool {
return (P[u] < P[v]);
});
}
vector<int> vs;
for (int i = 0; i < n; vs.push_back(us[i++]))
for (; vs.size() > 1 && sigtri(vs[vs.size() - 2], vs[vs.size() - 1], us[i]) <= 0; vs.pop_back()) {}
const int r = vs.size();
for (int i = (int)us.size() - 2; i >= 0; vs.push_back(us[i--]))
for (; (int)vs.size() > r && sigtri(vs[vs.size() - 2], vs[vs.size() - 1], us[i]) <= 0; vs.pop_back()) {}
if (vs.size() > 1) vs.pop_back();
return vs;
}
int S[18][18][18];
int can[18][18][18];
// (min, count)
using Pair = pair<int, Int>;
void update(Pair &t, const Pair &f, int c) {
c += f.first;
if (chmin(t.first, c)) t.second = 0;
if (t.first == c) t.second += f.second;
}
/*
dp[p][m]:
p: upper hull
edges 0-...-m are red
*/
Pair dp[1 << 18][18];
int main() {
for (int numCases; ~scanf("%d", &numCases); ) { for (int caseId = 1; caseId <= numCases; ++caseId) {
scanf("%d", &N);
P.resize(N);
for (int u = 0; u < N; ++u) {
scanf("%lld%lld", &P[u].x, &P[u].y);
}
for (int u = 0; u < N; ++u) for (int v = 0; v < N; ++v) {
scanf("%d", &W[u][v]);
}
{
vector<pair<Pt, int>> pus(N);
for (int u = 0; u < N; ++u) pus[u] = make_pair(P[u], u);
sort(pus.begin(), pus.end());
int WW[18][18];
for (int u = 0; u < N; ++u) for (int v = 0; v < N; ++v) WW[u][v] = W[u][v];
for (int u = 0; u < N; ++u) for (int v = 0; v < N; ++v) W[u][v] = WW[pus[u].second][pus[v].second];
sort(P.begin(), P.end());
}
// cerr<<"P = "<<P<<endl;
int lower = 0, upper = 0;
int base = 0;
{
vector<int> us(N);
for (int u = 0; u < N; ++u) us[u] = u;
const auto vs = convexHull(us);
const int vsLen = vs.size();
for (int h = 0; h < vsLen; ++h) {
const int u = vs[h];
const int v = vs[(h + 1) % vsLen];
if (u < v) {
lower |= 1 << u | 1 << v;
base += W[u][v];
} else {
upper |= 1 << u | 1 << v;
}
}
}
for (int u = 0; u < N; ++u) for (int v = 0; v < N; ++v) for (int w = 0; w < N; ++w) S[u][v][w] = sigtri(u, v, w);
for (int u = 0; u < N; ++u) for (int v = u + 1; v < N; ++v) for (int w = v + 1; w < N; ++w) {
can[u][v][w] = [&]() -> int {
const int s = S[u][v][w];
for (int x = 0; x < N; ++x) if (u != x && v != x && w != x) {
if (s == S[u][v][x] && s == S[v][w][x] && s == S[w][u][x]) {
// inside
return 0;
}
}
return s;
}();
}
vector<pair<Int, int>> es(1 << (N-2));
for (int q = 0; q < 1 << (N-2); ++q) {
const int p = 1 << 0 | q << 1 | 1 << (N-1);
Int area = 0;
for (int u = 0, v; u < N-1; u = v) {
v = __builtin_ctz(p & ~((1<<(u+1))-1));
area += (P[v].x - P[u].x) * (P[u].y + P[v].y);
}
es[q] = make_pair(area, p);
}
sort(es.begin(), es.end());
for (int p = 0; p < 1 << N; ++p) fill(dp[p], dp[p] + N, Pair(INF, 0));
dp[lower][0] = Pair(base, 1);
for (const auto &e : es) {
const int p = e.second;
// cerr<<"e = "<<e<<": ";for(int u=0;u<N;++u)if(p>>u&1)cerr<<u<<" ";cerr<<endl;
for (int m = 0; m < N; ++m) if (dp[p][m].first < INF) {
// cerr<<" m = "<<m<<": "<<dp[p][m]<<endl;
const int l = (m == 0) ? -1 : (31 - __builtin_clz(p & ((1<<m)-1)));
const int r = (m == N-1) ? N : __builtin_ctz(p & ~((1<<(m+1))-1));
// green -> red
if (m < N-1) {
update(dp[p][r], dp[p][m], 0);
}
// red|green -> + -> |green
if (0 < m && m < N-1) {
if (can[l][m][r] > 0) {
update(dp[p ^ 1 << m][l], dp[p][m], W[l][r]);
}
}
// |green -> - -> |green,green
if (m < N-1) {
for (int u = m + 1; u < r; ++u) if (can[m][u][r] < 0) {
update(dp[p | 1 << u][m], dp[p][m], W[m][u] + W[u][r]);
}
}
}
}
const Pair ans = dp[upper][N-1];
printf("%d %lld\n", ans.first, ans.second);
}
#ifndef LOCAL
break;
#endif
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 4148kb
input:
2 4 0 0 1 1 1 0 0 1 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 4 0 0 3 0 1 3 1 1 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0
output:
5 2 6 1
result:
ok 2 lines
Test #2:
score: 0
Accepted
time: 150ms
memory: 78848kb
input:
68 3 454 364 117 336 271 84 0 6 2 6 0 10 2 10 0 4 454 364 117 336 271 84 274 296 0 3 2 10 3 0 6 4 2 6 0 5 10 4 5 0 4 603 817 230 695 230 303 604 183 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 454 364 117 336 271 84 274 296 220 225 0 1 7 3 2 1 0 4 4 2 7 4 0 1 5 3 4 1 0 0 2 2 5 0 0 5 666667 788675 333173 78858...
output:
18 1 30 1 0 2 27 1 38 2 35 5 54 1 44 2 18 14 69 1 12 1 88 42 59 1 23 8 180 150 80 1 23 2 0 780 30 12 504 4550 30 4 19656 26888 29 6 26700 168942 24 88 22770 1098904 21 28 30816 7281984 24 27 15327 49789428 24 4 16338 342305320 21 48 42615 2410168190 22 360 44928 17309628327 1240448 1 2613579 1 19532...
result:
ok 68 lines
Extra Test:
score: -3
Extra Test Failed : Time Limit Exceeded on 2
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 ...