• [qzsc2019] 所以SARAZANMAI


    题目描述

    在平面上,每个人都和原点有一定的距离 $ r_i $ ,人与人之间的联系组成了一个多边形,就是这 $ n $ 个人所组成的凸包。凸包上人的顺序随意。

    最好的联系,所对应的多边形面积最大,那么这个多边形的面积是多少?

    输入格式

    第一行一个整数 $n$ 。

    接下来一行 $n$ 个整数依次表示 $ r_i $ 。

    输出格式

    输出一个实数表示答案, 要求绝对误差或相对误差≤$10^{-6}$

    样例

    input

    4

    5

    8

    58

    85

    output

    2970

    Sol

    拉格朗日乘数法
    考虑在$O(N!)$的时间内枚举点的相对位置
    则问题转化为 约束为$sum{x_i}=2π$ 求$sum{r_i*r_{i+1}*sin(xi)}$的极限


    构造$ F $ = $  sum{r_i*r_{i+1}*sin(x_i)+k*(sum{x_i}-2π)}$


    考虑对于每一个$x_i$求偏导数 并且使F的偏导数为0
    则可以发现 是联立形如$r_i*r_{i+1}*cos(xi)+k=0$的形式
    即联立多个$r_i*r_{i+1}*cos(xi)=t$的形式
    然后将这多个方程与$sum{x_i}=2π$联立
    可以发现的是所有的$x_i$关于$t$单调 二分一个$t$ 就可以在$O(n log(max( {ri*r_{i+1} ) }))$时间内求解答案
    总复杂度$O(n!*n*log(max{r_i*r_{i+1}}))$

    Code

    #include <bits/stdc++.h>
    using namespace std;
    int N,NN;
    int a[15];
    bool used[1005];
    double ans,pi=acos(-1.0);
    double r[1005];
    const double eps=1e-7;
    double Check(double Now){
        double ret=0.0;
        for (int i=1;i<=N;i++)
            ret=ret+acos(Now/r[a[i]]/r[a[i+1]]);
        return ret;    
    }
    double calc(){
        double l,rr=1e7;
        a[N+1]=a[1];
        for (int i=1;i<=N;i++)
            rr=min(rr,r[a[i]]*r[a[i+1]]);
        l=-rr;    
        while (rr-l>eps){
            double mid=(l+rr)/2.0;
            if (Check(mid)<2.0*pi)
                rr=mid;
            else l=mid;
            }
        if (Check(l)-2.0*pi>eps) return 0;
        double Ans=0.0;
        for (int i=1;i<=N;i++)
            Ans+=r[a[i]]*r[a[i+1]]*sin(acos(l/r[a[i]]/r[a[i+1]]));
        return Ans;
    }
    void dfs(int Len){
        if (Len>3) {
            a[Len]=a[1];
            N=Len-1;
            ans=max(ans,calc());
        }
        if (Len>NN) return;
        for (int i=1;i<=NN;i++)
            if (!used[i]){
                used[i]=true;
                a[Len]=i;
                dfs(Len+1);
                used[i]=false;
            }
    }
    int main(){
        scanf("%d",&N);
        NN=N;
        for (int i=1;i<=N;i++)
            cin>>r[i];
        dfs(1);
        printf("%.8lf
    ",ans/2.0);
        return 0;
    }

     

  • 相关阅读:
    第十七篇 ORM跨表查询和分组查询---二次剖析
    第十六篇随机验证码
    第十五篇 用户认证auth
    crawler_网络爬虫中编码的正确处理与乱码的解决策略
    java_Eclipse自动生成作者、日期注释等功能设置_导入 xml方式
    mysql_windows_安装版添加到服务开机自启动
    java_model_dao_自动生成_generator-mybatis-generator-1.3.2 基于maven插件
    java_eclipse_maven_svn_主题彩色插件_全屏插件
    mysql_MYSQL远程登录权限设置
    crawler_phantomjs_windows_linux下demo
  • 原文地址:https://www.cnblogs.com/si--nian/p/11328406.html
Copyright © 2020-2023  润新知