给你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; }