Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //#define __GLIBCXX_DEBUG
- #include <bits/stdc++.h>
- using namespace std;
- #define rep(i, n) for(int i = 0; i < (int)(n); ++i)
- #define pb push_back
- #define ALL(a) begin(a), end(a)
- #define all(a) begin(a), end(a)
- #define mp make_pair
- #define F first
- #define S second
- #define SZ(a) ((int)(a.size()))
- #define sz(a) ((int)(a.size()))
- typedef long long ll;
- typedef pair<int, int> PI;
- typedef complex<double> P;
- typedef pair<P, P> L;
- typedef vector<P> poly;
- const double EPS = 1e-9;
- #define DI(l) ((l).second-(l).first)
- #define EQ(a, b) (abs((a)-(b)) < EPS)
- #define CCW(l, a) ccw((l).first, (l).second, (a))
- namespace std {
- bool operator <(const P &a, const P &b) {
- return mp(real(a), imag(a)) < mp(real(b), imag(b));
- }
- }
- double cross(const P &a, const P &b) {return imag(conj(a)*b); }
- double dot(const P &a, const P &b) { return real(conj(a)*b); }
- int ccw(P a, P b, P c) {
- double d = cross(b -= a, c -= a);
- return d>EPS ? 1 : d < -EPS ? -1 : dot(b, c) < -EPS ? 2 : norm(b) + EPS < norm(c) ? -2 : 0;
- }
- bool parallel(const L &l, const L &m) { return EQ(cross(DI(l), DI(m)), 0); }
- P projection(const L &l, const P &p) { return l.first + dot(p-l.first, DI(l)) / norm(DI(l)) * DI(l); }
- P reflection(const L &l, const P &p) { return 2.0 * projection(l, p) - p; }
- bool intersectSS(const L &s, const L &t) {
- return CCW(s, t.first) * CCW(s, t.second) <= 0 && CCW(t, s.first)*CCW(t, s.second)<=0;
- }
- bool intersectSP(const L&s, const P&p) {
- return EQ(abs(s.first-p)+abs(s.second-p)-abs(DI(s)), 0);
- }
- bool sameline(const L &l, const L &m) {
- return parallel(l, m) && EQ(cross(DI(l), m.second-l.first), 0);
- }
- P crosspoint(const L &l, const L &m) {
- P a = DI(l), b = DI(m);
- double A = cross(a, b), B = cross(a, l.second-m.first);
- assert(!EQ(abs(A), 0));
- return m.first + B / A * b;
- }
- poly convex_cut(const poly &v, const L &l) {
- poly w;
- rep(i, sz(v)) {
- P a = v[i], b = v[(i+1)%sz(v)];
- if (CCW(l, a) != -1) w.push_back(a);
- if (CCW(l, a) * CCW(l, b) == -1) w.push_back(crosspoint(L(a, b), l));
- }
- return w;
- }
- void merge_segments(vector<L> &ls) {
- rep(i, sz(ls))
- if (ls[i].second < ls[i].first)
- swap(ls[i].second, ls[i].first);
- while(true) {
- bool updated = false;
- rep(i, sz(ls)) for(int j=i+1; j<sz(ls); j++) {
- if (sameline(ls[i], ls[j]) && !CCW(ls[i], ls[j].first)) {
- ls[i] = L(min(ls[i].first, ls[j].first), max(ls[i].second, ls[j].second));
- ls[j--] = ls.back();
- ls.pop_back();
- updated = true;
- }
- }
- if (!updated) break;
- }
- }
- vector<P> unique_points(vector<P> ps) {
- vector<P> res;
- for(auto p : ps) {
- bool ok = true;
- for(auto q : res) if (EQ(p, q)) {
- ok = false;
- break;
- }
- if (ok) res.push_back(p);
- }
- return res;
- }
- void stable_arrange(vector<L> ls, vector<vector<int> > &G, vector<P> &ps) {
- merge_segments(ls);
- rep(i, sz(ls)) {
- ps.push_back(ls[i].first);
- ps.push_back(ls[i].second);
- rep(j, i) if (intersectSS(ls[i], ls[j]) && !parallel(ls[i], ls[j]))
- ps.push_back(crosspoint(ls[i], ls[j]));
- }
- sort(all(ps));
- ps = unique_points(ps);
- G.assign(sz(ps), vector<int>());
- rep(i, sz(ls)) {
- vector<pair<double,int>> as;
- rep(j, sz(ps)) if (intersectSP(ls[i], ps[j]))
- as.push_back(mp(norm(ls[i].first-ps[j]), j));
- sort(all(as));
- rep(j, sz(as)-1) {
- int a = as[j].second, b = as[j+1].second;
- G[a].push_back(b);
- G[b].push_back(a);
- }
- }
- }
- double signed_area(const poly &v) {
- double res = 0;
- rep(i, sz(v)) res += cross(v[i], v[(i+1)%sz(v)]);
- return res * 0.5;
- }
- poly planar_dual(vector<P> ps, vector<vector<int> > g) {
- map<P, vector<pair<double,P>>> order;
- rep(i, sz(ps)) {
- vector<pair<double,P>> &a = order[ps[i]];
- rep(j, sz(g[i])) {
- P p = ps[g[i][j]];
- assert(p != ps[i]);
- a.emplace_back(arg(p-ps[i]), p);
- }
- sort(all(a));
- }
- map<L, int> M;
- rep(i, sz(g)) rep(j, sz(g[i])) {
- L l(ps[i], ps[g[i][j]]);
- if (M.count(l)) continue;
- poly v(1, l.first);
- while(l.second != ps[i]) {
- v.push_back(l.second);
- vector<pair<double, P>> &a = order[l.second];
- int index = lower_bound(all(a), make_pair(arg(l.first - l.second), l.first)) - a.begin();
- assert(index != sz(a));
- index = (index + sz(a)-1) % sz(a);
- l = L(l.second, a[index].second);
- }
- if (signed_area(v) <= 0) return v;
- }
- assert(false);
- }
- int main(int argc, char *argv[])
- {
- int n;
- while(cin >> n, n) {
- poly v(n);
- rep(i, n) {
- double x, y;
- cin >> x >> y;
- v[i] = P(x, y);
- }
- pair<int, double> best(0, 0);
- rep(i, sz(v)) rep(j, i) {
- P p = v[i], q = v[j];
- //cerr << i << " " << j << endl;
- L l((p+q)*0.5, (p+q)*0.5 - (q-p)*P(0, 1));
- poly w;
- for(auto p : v) w.push_back(reflection(l, p));
- reverse(all(w));
- const auto cv = v;
- v = convex_cut(v, l);
- w = convex_cut(w, l);
- if(0 && i == 2 && j == 0){
- cerr << endl;
- for(auto x : v){
- cerr << x << " ";
- }
- cerr << endl;
- for(auto x : w){
- cerr << x << " ";
- }
- cerr << endl;
- cerr << endl;
- }
- //cerr << "hoge" << endl;
- vector<L> ls;
- //cerr << "hoge" << endl;
- {
- vector<poly> ps;
- ps.pb(v);
- ps.pb(w);
- for(auto x : ps) {
- // for(auto p : x){
- // cerr << p << " ";
- // }
- // cerr << endl;
- rep(i, sz(x)) {
- ls.push_back(L(x[i], x[(i+1)%sz(x)]));
- }
- }
- }
- vector<P> ps;
- vector<vector<int>> G;
- stable_arrange(ls, G, ps);
- poly x = planar_dual(ps, G);
- double len = 0;
- int xsize = sz(x);
- rep(i, sz(x)) {
- len += abs(x[i] - x[(i+1)%sz(x)]);
- L l1(x[i], x[(i + 1)%sz(x)]);
- L l2(x[(i+1)%sz(x)], x[(i + 2)%sz(x)]);
- if(parallel(l1, l2)){
- --xsize;
- }
- }
- //printf("%d %.18f\n", xsize, len);
- best = max(best, mp(xsize, len));
- //printf("%d, %.8f\n", best.first, best.second);
- // for(auto p : x){
- // cerr << p << " " ;
- // }
- // cerr << endl;
- v = cv;
- }
- printf("%.18f\n", best.second);
- //exit(0);
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement