QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#638565#9458. Triangulationhos_lyricTL 150ms78848kbC++147.3kb2024-10-13 16:14:442024-10-13 18:03:04

Judging History

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

  • [2024-10-13 18:03:04]
  • 管理员手动重测本题所有提交记录
  • 测评结果:TL
  • 用时:150ms
  • 内存:78848kb
  • [2024-10-13 17:42:33]
  • hack成功,自动添加数据
  • (/hack/962)
  • [2024-10-13 17:27:13]
  • hack成功,自动添加数据
  • (/hack/961)
  • [2024-10-13 16:59:55]
  • hack成功,自动添加数据
  • (/hack/959)
  • [2024-10-13 16:55:19]
  • 自动重测本题所有获得100分的提交记录
  • 测评结果:97
  • 用时:144ms
  • 内存:78712kb
  • [2024-10-13 16:54:53]
  • hack成功,自动添加数据
  • (/hack/957)
  • [2024-10-13 16:14:46]
  • 评测
  • 测评结果:100
  • 用时:125ms
  • 内存:78616kb
  • [2024-10-13 16:14:44]
  • 提交

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

详细

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 ...

output:


result: