根据题意,每相邻两个点所产生的圆是相切的,所以可以根据题意建立一个方程
假设每一个点半径为r,每相邻两个点的距离是d(所有d都可求)
那么就有
r1+r2=d1
r2+r3=d2
r3+r4=d3
...
r(n-1)+r(n)=d(n-1)
r(n)+r(1)=d(n)
一:n为奇数
可以发现在n为奇数的时候联立所有方程,方程组是有解的
举个例子,n为3的时候有:
r1+r2=d1
r2+r3=d2
r3+r1=d3
联立解得2r1=d3-d2+d1
所以r1可以直接解出来,那么按序可以把所有的r都解出来
但是在计算过程中还需要判断r是否全为正数,全为正数才有解,否则无解
二:n为偶数
n为偶数的时候联立到最后一项发现不能解出某个点的r值
举个例子,n为4的时候有:
1.r1+r2=d1
2.r2+r3=d2
3.r3+r4=d3
4.r4+r1=d4
联立解得
r4+r1=d3-d2+d1
r4+r1=d4
不能解出某个点的r值,所以不能直接得到r1,按理来说只能枚举r1可能出现的所有值
但是如果要让面积最小,根据圆的面积公式
s=πr(1)²+πr(2)²+..+πr(n)²
由于其他所有的r都可以转化为r1的形式所以s其实是关于r1的一个一元二次方程,可以想到用三分来找到极小值
接下来只要知道r1的范围就能得到使s最小的r1了
求r1范围
由1. 得r1=r1 r1>=0
由1.2. 得r1=d1-r2 由于r2>=0,所以r1<=d1
由1.2.3. 得r1=d1-d2+r3>=0 由于r3>=0,所以r1>=d1-d2
由1.2.3.4得r1=d1-d2+d3-r4>=0 由于r4>=0,所以r1<=d1-d2+d3
所求r1的范围就是三分的范围(PS:如果求到的左端点l大于右端点r说明无解)
PS1:由于我的函数double cal(double r)中只是由d1,d2,d3...d(n-1)推出来的所有r
dn并没有用上所以在最后判断答案的时候为了体现dn,最后做了一个dn是否等于r1+rn的判定(注意是浮点数的判定)
PS2:我没注意到的一点就是浮点数在跟0进行比较的话,为了保险起见通常会设定一个精度使得fabs(x)<eps
#include <map>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define pp pop_back()
#define int long long
#define lowbit(x) ((x)&(-x))
#define double long double
#define sf(x) scanf("%lld",&x)
#define sff(x,y) scanf("%lld %lld",&x,&y)
#define all(x) (x).begin(), (x).end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
typedef unsigned long long ULL;
typedef pair<int,int>PII;
const int N=1e4+10,M=2*N,INF=4e18;
const double PI=acos(-1),eps=1e-5;
int n,m;
PII q[N];
double nowr[N],dist[N];
bool bl=false;
double get(PII a,PII b)
{
int aa=a.first-b.first;
int bb=a.second-b.second;
return sqrt(aa*aa+bb*bb);
}
int f(double x)
{
if(fabs(x)<eps||x>0)return 0;
return -1;
}
double cal(double r)
{
nowr[1]=r;
double sum=r*r;
for(int i=2;i<=n;i++)
nowr[i]=dist[i-1]-nowr[i-1],sum+=nowr[i]*nowr[i];
return sum*PI;
}
void solve()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)scanf("%lld %lld",&q[i].fi,&q[i].se);
for(int i=1;i<=n;i++)
if(i!=n)dist[i]=get(q[i],q[i+1]);
else dist[i]=get(q[i],q[1]);
if(n&1)
{
double now=0;
for(int i=1;i<=n;i++)
{
if(i&1)now+=dist[i];
else now-=dist[i];
}
bl=false;
double res=cal(now/2);
for(int i=1;i<=n;i++)
if(f(nowr[i])<0)
{
bl=true;
break;
}
if(bl)
{
puts("IMPOSSIBLE");
return;
}
printf("%.2Lf\n",res);
for(int i=1;i<=n;i++)printf("%.2Lf\n",nowr[i]);
}
else
{
double now=0;
double l=-INF,r=INF;
bl=false;
for(int i=1;i<=n;i++)
{
if(i&1)now+=dist[i],r=min(r,now);
else now-=dist[i],l=max(l,now);
}
if(l<0||l>r)
{
puts("IMPOSSIBLE");
return;
}
while(r-l>eps)
{
double k=(r-l)/3;
double midr=r-k;
double midl=l+k;
if(cal(midl)>=cal(midr))l=midl;
else r=midr;
}
for(int i=1;i<=n;i++)
if(f(nowr[i])<0)
{
bl=true;
break;
}
if(nowr[1]+nowr[n]-dist[n]>eps)//||fabs(nowr[1]+nowr[n]-dist[n])<-eps)
{
puts("IMPOSSIBLE");
return;
}
printf("%.2Lf\n",cal(l));
for(int i=1;i<=n;i++)printf("%.2Lf\n",nowr[i]);
}
return ;
}
signed main()
{
// IOS;
int T=1;
scanf("%lld",&T);
while(T--)
solve();
return 0;
}