给你N条线段的长度求能构成面积最大多边形的面积。
可以YY出,这N个点共圆,肯定是凸包。。。(自己证= =。。)
二分半径即可。
有一种情况是,所有共圆的时候,边都在一条直径的一侧,这样的话得特殊考虑。
判断是否是这种类型的话,可以假设最长边的一半为半径,然后求得除最长边的角度和,看是否小于180,如果小于,说明在一侧,二分的时候特殊判断。
卡精度卡死了,中间计算角度用acos过不去,用asin才可以,神马题啊都。。
非独立思考出来的题,囧。。不过确实是好题(被拍飞。。。><。。。)
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define FOR(i,s,t) for(int i=(s); i<(t); i++)
#define BUG puts("here!!!")
#define STOP system("pause")
#define file_r(x) freopen(x, "r", stdin)
#define file_w(x) freopen(x, "w", stdout)
using namespace std;
const int MAX = 110;
const double inf = 1e20;
const double pi = acos(-1.0);
double len[MAX];
const double eps = 1e-6;
bool dy(double x,double y) { return x > y + eps;} // x > y
bool xy(double x,double y) { return x < y - eps;} // x < y
bool dyd(double x,double y) { return x > y - eps;} // x >= y
bool xyd(double x,double y) { return x < y + eps;} // x <= y
bool dd(double x,double y) { return fabs( x - y ) < eps;} // x == y
double angle(double len, double r)
{
return asin(len/2/r)*2;
}
bool check(int n, double r, bool c)
{
FOR(i, 0, n)
if( xyd(2*r, len[i]) ) // r过小,构不成三角形
return true;
double ang1 = angle(len[0], r);
double ang2 = 0;
FOR(i, 1, n)
ang2 += angle(len[i], r);
if( !c )
{
if( ang1 + ang2 > 2 * pi )
return true;
return false;
}
if( ang1 > ang2 )
return true;
return false;
}
double area_triangle(double a,double b,double c)
{
double p = (a+b+c)/2.0;
return sqrt(p*(p-a)*(p-b)*(p-c));
}
double area_c(int n, double r)
{
double area = 0;
FOR(i, 0, n)
area += area_triangle(r, r, len[i]);
return area;
}
double solve(int n)
{
double begin, end, mid;
begin = len[0]/2;
end = inf;
int cnt = 0;
double ang = 0;
FOR(i, 1, n)
ang += angle(len[i], begin);
bool c = xy(ang, pi) ? true : false; // 是否是所有点都在一条直径的一侧
while( xyd(begin, end) )
{
if( cnt > 1 ) break;
if( dd(begin, end) )
cnt++;
mid = (begin + end)/2;
bool f = check(n, mid, c);
if( f )
begin = mid;
else
end = mid;
}
double area = area_c(n, mid);
if( c )
area -= 2 * area_triangle(len[0], mid, mid);
return area;
}
int main()
{
int n;
double sum;
while( ~scanf("%d", &n) )
{
sum = 0;
FOR(i, 0, n)
scanf("%lf", &len[i]);
sort(len, len+n, greater<double>() );
FOR(i, 1, n)
sum += len[i];
if( xyd(sum, len[0]) )
{
puts("0.00");
continue;
}
double ans = solve(n);
printf("%.2lf\n", ans);
}
return 0;
}