結果
問題 | No.2180 Comprehensive Line Segments |
ユーザー | MasKoaTS |
提出日時 | 2022-09-11 17:25:17 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 5,526 bytes |
コンパイル時間 | 3,582 ms |
コンパイル使用メモリ | 251,124 KB |
実行使用メモリ | 843,392 KB |
最終ジャッジ日時 | 2024-11-17 00:46:28 |
合計ジャッジ時間 | 82,165 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 34 ms
119,936 KB |
testcase_01 | AC | 3 ms
13,636 KB |
testcase_02 | AC | 2 ms
47,520 KB |
testcase_03 | TLE | - |
testcase_04 | WA | - |
testcase_05 | AC | 2 ms
35,492 KB |
testcase_06 | AC | 2 ms
6,816 KB |
testcase_07 | WA | - |
testcase_08 | AC | 3 ms
6,816 KB |
testcase_09 | AC | 121 ms
70,528 KB |
testcase_10 | MLE | - |
testcase_11 | MLE | - |
testcase_12 | TLE | - |
testcase_13 | TLE | - |
testcase_14 | MLE | - |
testcase_15 | MLE | - |
testcase_16 | MLE | - |
testcase_17 | TLE | - |
testcase_18 | TLE | - |
testcase_19 | TLE | - |
testcase_20 | AC | 17 ms
6,692 KB |
testcase_21 | TLE | - |
testcase_22 | AC | 129 ms
20,992 KB |
testcase_23 | AC | 3,650 ms
410,472 KB |
testcase_24 | AC | 859 ms
104,320 KB |
testcase_25 | MLE | - |
testcase_26 | MLE | - |
testcase_27 | MLE | - |
testcase_28 | MLE | - |
ソースコード
#include <bits/stdc++.h> #define rep(i, l, n) for (int i = (l); i < (n); i++) #define abs(x) (((x) < 0) ? -(x) : (x)) #define inf 1000000000 #define INF Fraction(1000000000ll, 1ll) using namespace std; using ll = long long; template <class T> using V = vector<T>; inline ll gcd(ll x, ll y) { x = abs(x); y = abs(y); while (y != 0) { ll r = x % y; x = y; y = r; } return x; } inline ll lcm(ll x, ll y) { ll g = gcd(x, y); return x / g * y; } struct Fraction { ll num; ll den; Fraction(void) { num = 0ll; den = 1ll; } Fraction(ll num, ll den) { assert(den != 0); this->num = num; this->den = den; } Fraction operator+(const Fraction other) const { ll l = lcm(this->den, other.den); ll a = l / this->den; ll b = l / other.den; ll nden = l, nnum = this->num * a + other.num * b; ll g = gcd(nden, nnum); return Fraction(nnum / g, nden / g); } Fraction operator-(const Fraction other) const { Fraction f = Fraction(-other.num, other.den); Fraction ret = (*this) + f; //cout << this->num << '/' << this->den << ", " << f.num << '/' << f.den << ", " << ret.num << '/' << ret.den << endl; return ret; } Fraction operator*(const Fraction other) const { ll nnum = this->num * other.num; ll nden = this->den * other.den; ll g = gcd(nden, nnum); return Fraction(nnum / g, nden / g); } Fraction operator/(const Fraction other) const { Fraction f = Fraction(other.den, other.num); Fraction ret = (*this) * f; return ret; } bool operator<(const Fraction other) const { ll l = lcm(this->den, other.den); ll a = l / this->den; ll b = l / other.den; return (this->num * a < other.num * b); } bool operator==(const Fraction other) const { ll l = lcm(this->den, other.den); ll a = l / this->den; ll b = l / other.den; return (this->num * a == other.num* b); } }; struct Point { Fraction x; Fraction y; Point(void) { x = Fraction(); y = Fraction(); } Point(Fraction x, Fraction y) { this->x = x; this->y = y; } bool operator<(const Point other) const { return tie(this->x, this->y) < tie(other.x, other.y); } bool isNull(void) { return (this->x == INF and this->y == INF); } }; struct Line { Fraction a; Fraction b; Fraction c; Line(void) { a = Fraction(); b = Fraction(); c = Fraction(); } Line(Fraction a, Fraction b, Fraction c) { this->a = a; this->b = b; this->c = c; } bool operator<(const Line other) const { return tie(this->a, this->b, this->c) < tie(other.a, other.b, other.c); } bool operator==(const Line other) const { return (this->a == other.a and this->b == other.b and this->c == other.c); } }; Line calcLine(Point one, Point other) { Fraction x1 = one.x, y1 = one.y; Fraction x2 = other.x, y2 = other.y; if (x1 == x2) { return Line(Fraction(1ll, 1ll), Fraction(0ll, 1ll), x1); } Fraction a = (y1 - y2) / (x1 - x2); Fraction c = y1 - a * x1; return Line(Fraction() - a, Fraction(1ll, 1ll), c); } Point intersection(Line one, Line other) { Fraction p = one.a * other.b - other.a * one.b; if (p == Fraction()) { return Point(INF, INF); } Fraction q = other.b * one.c - one.b * other.c; Fraction x = q / p; Fraction y = (one.b == Fraction()) ? ((other.c - other.a * x) / other.b) : ((one.c - one.a * x) / one.b); return Point(x, y); } /* * Main Code */ int main(void) { int N; cin >> N; V<Point> P(N); rep(i, 0, N) { ll x, y; cin >> x >> y; P[i] = { Fraction(x,1ll),Fraction(y,1ll) }; } if (N == 1) { cout << 1 << endl; return 0; } map<Point, int> ph = {}; int pt_id = 0; for (Point p : P) { ph[p] = pt_id; pt_id++; } int ln_id = 0; map<Line, int> lh = {}; V<Line> vec = {}; rep(i, 0, N - 1) { rep(j, 1, N) { Point p1 = P[i], p2 = P[j]; Line l = calcLine(p1, p2); if (lh.find(l) != lh.end()) { continue; } lh[l] = ln_id; ln_id++; vec.push_back(l); } } rep(i, 0, ln_id - 1) { rep(j, 1, ln_id) { Line l1 = vec[i], l2 = vec[j]; Point p = intersection(l1, l2); if (p.isNull() or ph.find(p) != ph.end()) { continue; } P.push_back(p); ph[p] = pt_id; pt_id++; } } V<V<pair<int, int> > > dir_lis(pt_id, V<pair<int, int> >(pt_id, pair<int, int>({ inf,0 }))); rep(i, 0, pt_id - 1) { rep(j, 1, pt_id) { Point p1 = P[i], p2 = P[j]; Line l = calcLine(p1, p2); if (lh.find(l) == lh.end()) { continue; } dir_lis[i][j] = { lh[l], (p1 < p2) }; dir_lis[j][i] = { lh[l], (p2 < p1) }; } } V<V<V<V<int> > > > dp(1 << N, V<V<V<int> > >(pt_id, V<V<int> >(ln_id + 1, V<int>(2, inf)))); deque<V<int> > que = {}; rep(i, 0, N) { que.push_back({ 0, 1 << i, i, ln_id, 0 }); dp[1 << i][i][ln_id][0] = 0; } int goal = (1 << N) - 1; int ans = inf; int cnt = 0; while (que.empty() == false) { //cout << que.size() << endl; V<int> vec = que.front(); que.pop_front(); int c = vec[0], b = vec[1], v = vec[2], l = vec[3], a = vec[4]; if (l != ln_id and c > dp[b][v][l][a]) { continue; } if (b == goal) { ans = c; break; } rep(nv, 0, pt_id) { int nb = (nv < N) ? (b | (1 << nv)) : b; if (dir_lis[v][nv].first == inf) { continue; } int nl = dir_lis[v][nv].first, na = dir_lis[v][nv].second; int nc = c; if (l == ln_id or l != nl or a != na) { nc++; } if (nc >= dp[nb][nv][nl][na]) { continue; } dp[nb][nv][nl][na] = nc; if (nc == c) { que.push_front({ nc, nb, nv, nl, na }); } else { que.push_back({ nc, nb, nv, nl, na }); } } } cout << ans << endl; return 0; }