###### HDU 5531 (平面几何 三分)

#include <bits/stdc++.h>
using namespace std;
#define maxn 11111
#define eps 1e-7
#define pi acos (-1)

struct point {
double x, y;
}p[maxn];
double l[maxn]; //存第i条边到i+1条边的距离
double g[maxn]; //存l[n-1]-l[n-2]+l[n-3]-l[n-4]...
double ans[maxn]; //第i个圆的面积
int n;
double A, B, C; //二次函数的三个参数Ax^2+Bx+C

double dis (point a, point b) {
double xx = a.x-b.x, yy = a.y-b.y;
return sqrt (xx*xx + yy*yy);
}

double f (double x) {
return A*x*x + B*x + C;
}

void work (double &L, double &R) {
l[0] = l[n];
L = 0, R = min (l[0], l[1]);
for (int i = 1; i <= n; i++) {
if (i&1) {
L = max (L, -1*g[i]);
R = min (R, min (l[i-1], l[i])-g[i]);
}
else {
L = max (L, g[i]-min (l[i-1], l[i]));
R = min (R, g[i]);
}
}
return ;
}

void solve_even () { //n是偶数
if (fabs (l[n]-g[n]) > eps) { //无解
printf ("IMPOSSIBLE\n");
return ;
}
A = n;
B = C = 0.0;
for (int i = 1; i <= n; i++) {
int id = ((i&1)? 1 : -1); //-x还是+x
B += 2.0*g[i]*id;
C += g[i]*g[i];
}
double L, R, LL, RR;
work (L, R); //找到x的范围
if (L > R) {
printf ("IMPOSSIBLE\n");
return ;
}
while (R-L > eps) {
LL = (L*2+R)/3, RR = (L+2*R)/3;
double p1 = f (LL), p2 = f (RR);
if (p1 > p2)
L = LL;
else
R = RR;
}
double x = (L+R)/2.0; //第一个半径为x的时候总面积最小
bool ok = 1;
memset (ans, 0, sizeof ans);
for (int i = 1; i <= n; i++) {
int id = ((i&1)? 1 : -1); //+x还是-x
double cur = g[i]+x*id; //当前半径
if (cur >= 0) {
ans[i] = cur;
}
else { //出现了负数
ok = 0;
break;
}
}
if (!ok) {
printf ("IMPOSSIBLE\n");
return ;
}
double sum = 0.0;
for (int i = 1; i <= n; i++) {
sum += ans[i]*ans[i];
}
printf ("%.2f\n", sum*pi);
for (int i = 1; i <= n; i++)
printf ("%.2f\n", ans[i]);
return ;
}

void solve_odd () { //n是奇数
double x = (l[n]-g[n]) / 2.0;
bool ok = 1;
memset (ans, 0, sizeof ans);
for (int i = 1; i <= n; i++) {
int id = ((i&1)? 1 : -1); //+x还是-x
double cur = g[i]+x*id; //当前半径
if (cur >= 0) {
ans[i] = cur;
}
else { //出现了负数
ok = 0;
break;
}
}
if (!ok) {
printf ("IMPOSSIBLE\n");
return ;
}
double sum = 0.0;
for (int i = 1; i <= n; i++) {
sum += ans[i]*ans[i];
}
printf ("%.2f\n", sum*pi);
for (int i = 1; i <= n; i++)
printf ("%.2f\n", ans[i]);
return ;
}

int main () {
//freopen ("in", "r", stdin);
int t;
scanf ("%d", &t);
while (t--) {
scanf ("%d", &n);
for (int i = 1; i <= n; i++) {
scanf ("%lf%lf", &p[i].x, &p[i].y);
}
p[n+1] = p[1];
for (int i = 1; i <= n; i++) {
l[i] = dis (p[i], p[i+1]);
}
g[1] = 0;
for (int i = 2; i <= n; i++) {
g[i] = l[i-1]-g[i-1];
}
if (n&1)
solve_odd ();
else
solve_even ();
}
return 0;
}


#### HDU 5531 Rebuild(三分)

2016-10-09 23:18:32

#### HDU 5531 Rebuild （三分） ★ ★

2016-10-06 11:27:40

#### hdu 5531 Rebuild（三分）

2015-11-02 10:32:05

#### HDU 5531(Rebuild- 三分)

2016-07-08 03:37:03

#### hdu 5531 Rebuild 三分

2015-11-02 18:20:16

#### HDU 5531 Rebuild 相切的圆们

2015-11-01 13:25:37

#### hdu 2438 Turn the corner（三分）

2015-02-04 16:08:36

#### HDU 3400 Line belt （三分再三分）

2014-09-18 17:16:14

#### [hdu] 6097 "优秀的黄金分割三分"

2017-08-11 14:26:32

#### hdu2899 (三分/二分/模拟退火)

2017-04-20 17:52:09

## 不良信息举报

HDU 5531 (平面几何 三分)