1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
| #include <bits/stdc++.h> using namespace std; const int N = 3e2 + 5; typedef long long i64; typedef double db; typedef pair<int,int> pii; #define FI first #define SE second const db eps = 1e-9,PI = acos(-1.0); mt19937 Rnd(time(0)); struct Vec { int x,y; Vec(){} Vec(const int _x,const int _y):x(_x),y(_y){} inline Vec operator + (const Vec &rhs) const { return Vec(x + rhs.x,y + rhs.y);} inline Vec operator - (const Vec &rhs) const { return Vec(x - rhs.x,y - rhs.y);} inline i64 operator * (const Vec &rhs) const { return 1ll * x * rhs.y - 1ll * y * rhs.x;} inline bool operator == (const Vec &rhs) const { return x == rhs.x && y == rhs.y;} }; Vec O(0,0); inline bool Cmp(const Vec &x,const Vec &y) { return (x.x != y.x) ? (x.x < y.x) : (x.y < y.y);} inline i64 Dot(const Vec &A,const Vec &B) { return 1ll * A.x * B.x + 1ll * A.y * B.y;} inline db Distance(const Vec &A,const Vec &B) { return sqrt(Dot(A - B,A - B));} inline db Area(const Vec &A,const Vec &B,const Vec &C) { return 0.5 * abs(A * B + B * C + C * A);} inline bool Equal(const db &A,const db &B) { return fabs(A - B) < eps;} inline bool InSegment(const Vec &A,const Vec &B,const Vec &p) { return Equal(Distance(A,p) + Distance(p,B),Distance(A,B));} inline bool InTriangle(const Vec &A,const Vec &B,const Vec &C,const Vec &p) { if((B - A) * (p - A) >= 0 && (C - B) * (p - B) >= 0 && (A - C) * (p - C) >= 0) return true; if((B - A) * (p - A) <= 0 && (C - B) * (p - B) <= 0 && (A - C) * (p - C) <= 0) return true; return false; } inline Vec Rotate(const Vec &A) { return Vec(-A.y,A.x);} inline int sgn(const Vec &A) { return A.x > 0 || A.x == 0 && A.y > 0;} Vec p[N]; int n; int V[N][N],VL[N][N]; int TagO; db sum[N][N]; inline int NeedAdd(const Vec &A,const Vec &B,const Vec &p) { if(!InTriangle(O,A,B,p)) return 0; if(!p.x && !p.y) return 0;
if((O - p) * (A - p) == 0 || (O - p) * (B - p) == 0 || (A - p) * (B - p) == 0) return 1; return 2; } inline bool CheckTriangle(int i,int j,int k) { if(InSegment(p[i],p[j],p[k])) return VL[i][j] <= 1; if(InSegment(p[i],p[k],p[j])) return VL[i][k] <= 1; if(InSegment(p[j],p[k],p[i])) return VL[j][k] <= 1; int tmp = TagO - (p[i] == O) - (p[j] == O) - (p[k] == O); if(tmp && InTriangle(p[i],p[j],p[k],O)) return false; if(VL[i][j] || VL[j][k] || VL[i][k]) return false;
int num = 0; int v1 = V[i][j] - NeedAdd(p[i],p[j],p[k]); int v2 = V[j][k] - NeedAdd(p[j],p[k],p[i]); int v3 = V[k][i] - NeedAdd(p[k],p[i],p[j]); if(p[i] * p[j] > 0) num += v1; else if(p[i] * p[j] < 0) num -= v1; if(p[j] * p[k] > 0) num += v2; else if(p[j] * p[k] < 0) num -= v2; if(p[k] * p[i] > 0) num += v3; else if(p[k] * p[i] < 0) num -= v3;
return num == 0; }
struct Line { int s,t,type; Vec v; Line(){} Line(const int _s,const int _t,const int _type,const Vec _v): s(_s),t(_t),type(_type),v(_v){} inline bool operator < (const Line &rhs) const { int t1 = sgn(this->v),t2 = sgn(rhs.v); if(t1 != t2) return t1 > t2; i64 val = this->v * rhs.v; if(val) return val > 0; else return type < rhs.type; } }; Line L[N * N * 2]; int tot; inline void Init() { cin >> n; for(int i = 1;i <= n;i++) cin >> p[i].x >> p[i].y; TagO = 0; for(int i = 1;i <= n;i++) if(p[i] == O) TagO++; sort(p + 1,p + n + 1,Cmp); for(int i = 1;i <= n;i++) for(int j = 1;j <= n;j++) if(i < j) for(int k = 1;k <= n;k++) { if(k == i || k == j) continue; if(p[k] == O) continue; if(!InTriangle(p[i],O,p[j],p[k])) continue; V[i][j] += NeedAdd(p[i],p[j],p[k]); if(InSegment(p[i],p[j],p[k])) ++VL[i][j]; } else V[i][j] = V[j][i],VL[i][j] = VL[j][i]; for(int i = 1;i <= n;i++) for(int j = 1;j <= n;j++) for(int k = 1;k <= n;k++) { if(k == i || k == j) continue; if((p[k] - p[i]) * (p[j] - p[i]) <= 0) continue; if(Dot(p[j] - p[i],p[k] - p[i]) >= 0 && Dot(p[i] - p[j],p[k] - p[j]) > 0) sum[i][j] += min(Distance(p[k],p[i]),Distance(p[k],p[j])); } for(int i = 1;i <= n;i++) for(int j = 1;j <= n;j++) { if(i == j) continue; sum[i][j] += Distance(p[i],p[j]); L[++tot] = Line(i,j,0,p[j] - p[i]); L[++tot] = Line(i,j,1,Rotate(p[j] - p[i])); } sort(L + 1,L + tot + 1); cerr << 1.0 * clock() / CLOCKS_PER_SEC << endl; }
db dp[N]; inline bool Check(int st,db mid) { for(int i = 1;i <= n;i++) dp[i] = -1e15; dp[st] = -eps;
for(int i = 1;i <= tot;i++) { int s = L[i].s,t = L[i].t,tp = L[i].type; if(tp == 1) { if(s >= st) dp[s] -= mid * Distance(p[s],p[t]); } else if(s >= st && t >= st && CheckTriangle(st,s,t)) dp[t] = max(dp[t],dp[s] + Area(p[st],p[s],p[t]) - mid * sum[s][t]); }
return dp[st] > eps; } inline void Clr(int n) { for(int i = 1;i <= n;i++) for(int j = 1;j <= n;j++) V[i][j] = VL[i][j] = sum[i][j] = 0; tot = 0; } inline void work() { Clr(n); Init(); static int perm[N]; for(int i = 1;i <= n;i++) perm[i] = i; shuffle(perm + 1,perm + n + 1,Rnd); db ans = 0;
for(int i = 1;i <= n;i++) if(Check(perm[i],ans)) { db lef = ans,rig = 1e6; for(int _ = 1;_ <= 45;_++) { db mid = (lef + rig) / 2; if(Check(perm[i],mid)) lef = mid; else rig = mid; } ans = lef; } printf("%.10lf\n",ans); cerr << 1.0 * clock() / CLOCKS_PER_SEC << endl; } int main() { int T; cin >> T; while(T--) work(); return 0; }
|