原题见HDU 5531
依次输入n个点的坐标,分别为圆心。保证相邻圆心的距离是个正整数。第n个圆和第1个圆相邻。要求相邻两个圆要相切,求全部圆面积和的最小值,以及此时半径的取法。
先根据坐标求出相邻圆心距离依次为
a0,a1,...,an−1
设圆半径分别为
x0,x1,...,xn−1
化为方程,即:
⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪x0+x1=a0x1+x2=a1x2+x3=a2...xn−1+x0=an−1①
则x0可以代替所有其他的xi
,如下:
⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪x1=a0−x0x2=a1−a0+x0x3=a2−a1+a0−x0...xn−1=an−1−an−2+...+(−1)(n−1)x0
令xi=bi+ci∗x0
,则
b0=0,c0=1
bi=ai−1−bi−1, ci=−ci−1
将 xn−1=bn−1+cn−1∗x0 代入到①式,则
(cn−1+1)x0=an−1−bn−1
当cn−1=1时,方程有唯一解x0,只要在代入其他xi过程中不产生负数,即是一组解。否则无解。
当cn−1=−1时,若an−1−bn−1不为0,则方程无解。否则有多解。
考虑多解的情况。
∑x2i=∑(b2i+2bicix0+c2ix20)=nx20+2(∑bici)xi+∑b2i
化为二次方程的情形,则只需考虑
m=−∑bicin可取的x0
的区间范围。
而 x0 的范围由 xi 不小于0决定。
附code
/*--------------------------------------------
* File Name: HDU 5531
* Author: Danliwoo
* Mail: Danliwoo@outlook.com
* Created Time: 2015-11-01 22:38:00
--------------------------------------------*/
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const double Pi = acos(-1);
int n;
struct point{
LL x, y;
void sc(){
scanf("%I64d%I64d", &x, &y);
}
LL dis(point b){
LL d = (x-b.x)*(x-b.x)+(y-b.y)*(y-b.y);
LL c = sqrt(d);
return c;
}
}p[10010];
LL a[10010], b[10010], c[10010];
double x[10010];
void give(double y)
{
double s = 0;
if(y < 0){
printf("IMPOSSIBLE\n");
return;
}
x[0] = y;
s += pow(x[0], 2);
for(int i = 1;i < n;i++)
{
x[i] = b[i]+c[i]*x[0];
if(x[i] < 0){
printf("IMPOSSIBLE\n");
return;
}
s += pow(x[i],2);
}
s *= Pi;
printf("%.2f\n", s);
for(int i = 0;i < n;i++)
printf("%.2f\n", x[i]);
}
void solve()
{
double L = 0, R = a[0];
for(int i = 2;i < n;i++)
{
if(c[i] == 1)
L = max(L, -1.0*b[i]);
else if(c[i] == -1)
R = min(R, 1.0*b[i]);
if(L > R)
{
printf("IMPOSSIBLE\n");
return;
}
}
double B = 0;
for(int i = 0;i < n;i++)
B += 2*b[i]*c[i];
double m = -B/n/2.0;
if(R < m)
give(R);
else if(L > m)
give(L);
else
give(m);
}
int main()
{
int T;
scanf("%d", &T);
while(T--){
scanf("%d", &n);
for(int i = 0;i < n;i++)
p[i].sc();
for(int i = 0;i < n;i++)
a[i] = p[i].dis(p[(i+1)%n]);
b[0] = 0; c[0] = 1;
for(int i = 1;i < n;i++)
{
c[i] = -c[i-1];
b[i] = a[i-1]-b[i-1];
}
if(c[n-1] == 1)
{
give((a[n-1]-b[n-1])/2.0);
continue;
}
if(b[n-1] != a[n-1])
{
printf("IMPOSSIBLE\n");
continue;
}
solve();
}
return 0;
}