[Jzoj5606]Yja

题意

你需要找到 n n 个点,每个点离原点的距离分别为R1,R2,,Rn n n 个点形成的凸包的最大面积是多少?(不要求所有 n n 个点都在凸包上)

题解

看到n8,想这题怕不是爆搜 ? ?

假设搜出了m个点,分别是 a1am a 1 … a m ,为了方便令 am+1=a1 a m + 1 = a 1

根据多边形面积的定义可以知道我们要最大化的就是 12mi=1rairai+1sinxi 1 2 ∑ i = 1 m r a i r a i + 1 sin ⁡ x i ,其中 mi=1xi=2π ∑ i = 1 m x i = 2 π

这是要求一个有条件最值,考虑用拉格朗日乘数法来试一试

f(x1,,xn)=mi=1rairai+1sinxi,g(x1,,xn)=mi=1xi=2π f ( x 1 , … , x n ) = ∑ i = 1 m r a i r a i + 1 sin ⁡ x i , g ( x 1 , … , x n ) = ∑ i = 1 m x i = 2 π

在这题里面

f+(λ)gxi=rairai+1cosxi+(λ)=0i=1mxi=i=1marccosλrairai+1=2π ∂ f + ( − λ ) g ∂ x i = r a i r a i + 1 cos ⁡ x i + ( − λ ) = 0 ⇒ ∑ i = 1 m x i = ∑ i = 1 m arccos ⁡ λ r a i r a i + 1 = 2 π

这是 arccos arccos 的函数图像

然后考虑到 arccos arccos 是单调递减的所以可以二分求出当前的 λ λ

注意 λ[min{rairai+1},min{rairai+1}] λ ∈ [ − m i n { r a i r a i + 1 } , m i n { r a i r a i + 1 } ]

#include<bits/stdc++.h>
#define fp(i,a,b) for(register int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
#define go(u) for(register int i=fi[u],v=e[i].to;i;v=e[i=e[i].nx].to)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=10;
const double eps=1e-8,pi2=2*acos(-1);
typedef int arr[N];
int n,vis[N];double ans,p[N],q[N],r[N];
inline void chk(int m){
    double L,R,T=1e6,mid,tp;p[m+1]=p[1];
    fp(i,1,m)q[i]=p[i]*p[i+1],cmin(T,q[i]);L=-(R=T);
    while(R-L>eps){
        mid=(L+R)*0.5;tp=0;
        fp(i,1,m)tp+=acos(mid/q[i]);
        if(tp>=pi2)L=mid;
        else R=mid;
    }tp=0;if(T-L<eps)return;
    fp(i,1,m)tp+=q[i]*sin(acos(L/q[i]));
    cmax(ans,tp);
}
void dfs(int d){
    if(d>3)chk(d-1);if(d==n+1)return;
    fp(i,1,n-2)if(!vis[i])p[d]=r[i],vis[i]=1,dfs(d+1),vis[i]=0;
}
int main(){
    // #ifndef ONLINE_JUDGE
        file("yja");
    // #endif
    scanf("%d",&n);
    fp(i,1,n)scanf("%lf",r+i);sort(r+1,r+n+1);
    p[1]=r[n],p[2]=r[n-1];dfs(3);
    printf("%.6lf",ans*0.5);
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值