剧毒题,可以其他半径都用第一个半径表示
然后求出范围,在范围内三分找极值点
有两个trick,要讨论n的奇偶
如果n是奇数,那么一个等式,可以画出两个r0,然后就直接求出了r0的值
直接就能算
如果n是偶数,那么最后是一个等式,需要判左右是否相等,也就是奇数边减去偶数边是否等于0
三分等于号在l那就用l,在r那就用r,不然wa到死
代码:
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std;
#define MAX 100005
#define MAXN 1000005
#define maxnode 105
#define sigma_size 30
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lrt rt<<1
#define rrt rt<<1|1
#define middle int m=(r+l)>>1
#define LL long long
#define ull unsigned long long
#define mem(x,v) memset(x,v,sizeof(x))
#define lowbit(x) (x&-x)
#define pii pair<int,int>
#define bits(a) __builtin_popcount(a)
#define mk make_pair
#define limit 10000
//const int prime = 999983;
const int INF = 0x3f3f3f3f;
const LL INFF = 0x3f3f;
const double pi = acos(-1.0);
const double inf = 1e18;
const double eps = 1e-8;
const LL mod = 1e9+7;
const ull mx = 133333331;
/*****************************************************/
inline void RI(int &x) {
char c;
while((c=getchar())<'0' || c>'9');
x=c-'0';
while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
}
/*****************************************************/
double cal(double a,double b){
return sqrt(a*a+b*b);
}
double x[10005],y[10005];
vector<double> ans;
int n;
double get(double a){
double ret=a*a;
ans.clear();
ans.push_back(a);
for(int i=1;i<n;i++){
double tmp=cal(x[i]-x[i-1],y[i]-y[i-1]);
a=tmp-a;
ret+=a*a;
ans.push_back(a);
}
return ret;
}
int main(){
int t;
cin>>t;
while(t--){
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%lf%lf",&x[i],&y[i]);
double l=0,r=inf;
double tmp=0;
double cnt=0;
for(int i=0;i<n;i++){
int j=(i+1)%n;
tmp=cal(x[i]-x[j],y[i]-y[j])-tmp;
cnt=cal(x[i]-x[j],y[i]-y[j])-cnt;
if(i%2) l=max(l,-tmp);
else r=min(r,tmp);
}
if(l>r||(n%2==0&&fabs(cnt)>eps)) printf("IMPOSSIBLE\n");
else{
if(n%2){
cnt/=2;
printf("%.2f\n",get(cnt)*pi);
for(int i=0;i<ans.size();i++) printf("%.2f\n",ans[i]);
}
else{
for(int i=0;i<100;i++){
double mid1=(2*l+r)/3;
double mid2=(l+2*r)/3;
if(get(mid1)>get(mid2)) l=mid1;
else r=mid2;
}
printf("%.2f\n",get(r)*pi);
for(int i=0;i<ans.size();i++) printf("%.2f\n",ans[i]);
}
}
}
return 0;
}