# HDU 5531 (平面几何 三分)

401人阅读 评论(0)

#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;
}


0
0

* 以上用户言论只代表其个人观点，不代表CSDN网站的观点或立场
个人资料
• 访问：101036次
• 积分：5430
• 等级：
• 排名：第5109名
• 原创：463篇
• 转载：0篇
• 译文：0篇
• 评论：14条
评论排行
最新评论