Hatena::Grouptopcoder

れんしゅうちょう。 このページをアンテナに追加 RSSフィード

2015-06-26ICPC2015 国内予選 G (参加記でゎない)

notさんのを見習って僕も書いてみた.

方針zerokugiさんのと同じ.

線分をむりやり符号付きにしてやると楽なようだ.

サンプルは通った.

ライブラリ除いて50行くらい.

#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < (n); ++i)

#define X real()
#define Y imag()
using R = long double;
using P = complex<R>;
using L = pair<P, P>;
const R EPS = 1E-8;
#define fst first
#define snd second
inline int sgn(const R &r){ return (r > EPS) - (r < -EPS); }
inline int sgn(const R &a, const R &b){ return sgn(a-b); }
namespace std{
    bool operator<(const P &a, const P &b){
        return sgn(a.X, b.X) ? a.X < b.X : sgn(a.Y, b.Y) < 0;
    }
}
inline R dot(const P &a, const P &b){ return real(conj(a) * b); }
inline R det(const P &a, const P &b){ return imag(conj(a) * b); }
inline P vec(const L &l){ return l.snd - l.fst; }
enum CCW{FRONT = 1, RIGHT = 2, BACK = 4, LEFT = 8, ON = 16, };
inline int ccw(const L &l, const P &p){
    P b = p - l.fst, c = l.snd - l.fst;
    if(int scr = sgn(det(c, b))) return scr < 0 ? RIGHT : LEFT;
    if(sgn(dot(c, b)) < 0) return BACK;
    return sgn(norm(c), norm(b)) < 0 ? FRONT : ON;
}
inline vector<P> pLL(const L &l, const L &m){
    if(sgn(det(vec(l), vec(m))) == 0) return vector<P>(0);
    R A = det(vec(m), vec(l));
    R B = det(vec(m), m.snd - l.fst);
    return vector<P>(1, l.fst + B / A * vec(l));
}
inline P refLP(const L &l, const P &p){
    return (R)(2) * (l.fst + dot(p - l.fst, vec(l)) / norm(vec(l)) * vec(l)) - p;
}
vector<P> cut(const vector<P> &pol, const L &l){
    vector<P> res;
    rep(i, pol.size()-1){
        P a = pol[i], b = pol[i+1];
        L s(a, b);
        if(ccw(l, a) != RIGHT) res.emplace_back(a);
        if(sgn(det(vec(l), s.fst-l.fst)) * sgn(det(vec(l), s.snd-l.fst)) < 0)
            res.emplace_back(pLL(l, s).front());
    }
    res.emplace_back(res.front());
    return res;
}

bool solve(){
    int n; cin >> n;
    if(!n) return false;
    vector<P> in(n);
    for(auto &p : in){ R x, y; cin >> x >> y; p.real(x); p.imag(y); }
    in.emplace_back(in.front());
    pair<int, R> res(-1, 0);
    rep(i, n) rep(j, i){
        L l((in[i] + in[j]) / (R)(2), P(0, 0));
        l.snd = l.fst + P(0, 1) * (in[i] - in[j]);

        vector<P> a = cut(in, l); swap(l.fst, l.snd);
        vector<P> b = cut(in, l);
        for(auto &p : b) p = refLP(l, p);
        reverse(begin(b), end(b));

        vector<P> c = b;
        rep(i, a.size()-1) c = cut(c, L(a[i], a[i+1]));

        vector<P> ps;
        for(auto &p : a) ps.emplace_back(p);
        for(auto &p : b) ps.emplace_back(p);
        for(auto &p : c) ps.emplace_back(p);
        auto near = [](const P &a, const P &b){ return sgn(abs(a-b)) == 0; };
        sort(begin(ps), end(ps));
        ps.erase(unique(begin(ps), end(ps), near), end(ps));

        vector<pair<L, int>> ls;
        rep(i, a.size()-1) ls.emplace_back(L(a[i], a[i+1]), +1);
        rep(i, b.size()-1) ls.emplace_back(L(b[i], b[i+1]), +1);
        rep(i, c.size()-1) ls.emplace_back(L(c[i], c[i+1]), -1);

        R len = 0;
        for(auto &ld : ls) len += ld.snd * abs(ld.fst.snd - ld.fst.fst);

        map<pair<int, int>, int> es;
        for(auto &ld : ls){
            vector<pair<P, int>> qs;
            rep(i, ps.size()) if(ccw(ld.fst, ps[i]) == ON) qs.emplace_back(ps[i], i);
            sort(begin(qs), end(qs));
            rep(i, qs.size()-1) es[make_pair(qs[i].snd, qs[i+1].snd)] += ld.snd;
            rep(i, qs.size()-1) es[make_pair(qs[i+1].snd, qs[i].snd)] += ld.snd;
        }
        int cnt = 0;
        vector<vector<P>> g(ps.size());
        for(auto &e : es) if(e.snd) g[e.fst.fst].emplace_back(ps[e.fst.snd]);
        for(auto &v : g) assert(v.size() == 0 or v.size() == 2);
        rep(i, g.size()) if(g[i].size() == 2) cnt += ccw(L(g[i][0], g[i][1]), ps[i]) != ON;
        res = max(res, make_pair(cnt, len));
    }
    printf("%.6Lf\n", res.snd);
    return true;
}

int main(void){
    while(solve());
}