URAL 1159. Fence


N本の線分の長さに面積の最大の多角形を構成する面積を求めます.
YY出てもいいですが、このN点が共に丸くて、きっと凸包に違いありません...(自己証==..)
二分半径でいいです.
一つのケースは、すべての共円の場合、辺が1本の直径の側にあるということです.これは特に考慮しなければなりません.
このタイプかどうかを判断すると、最長辺の半分を半径と仮定して、最長辺を除く角度和を求め、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
", ans); } return 0; }