【拉格朗日乘数法】bzoj2876: [Noi2012]骑行川藏

题目链接

普及一下拉格朗日乘数法。
知识链接

问题:求 f(a,b,c,...) 的极值,其中 g(a,b,c,...)=0
即一个多元式在某一限制下的极值。

f+λg=0
于是有:

f(a)+λg(a)=0

f(b)+λg(b)=0

......

g(a,b,c,...)=0

n 个方程,n个未知数,理论上是可以求出 a,b,c,... 的具体值的。

对于此题,拉格朗日的方程为:

siv2i+2λkisi(vivi)=0

化简一下:
2λkiv2i(vivi)=1

二分一下 λ ,然后求出每一个方程的解检验一下即可。

#include <iostream>
#include <cstdio>
#include <cmath>
#define eps 1e-12
#define MAXN 10005
using namespace std;

int n;
double s[MAXN], k[MAXN], v[MAXN], E, vv[MAXN], vmax[MAXN];

double cal(double num)
{
    double sum=0, l, r, mid, a, b;
    for(int i=1;i<=n;++i)
    {
        l=v[i], r=vmax[i];
        a=2*num*k[i], b=-a*v[i];
        while(l+eps<r)
        {
            mid=(l+r)/2;
            if(a*mid*mid*mid+b*mid*mid-1>0)r=mid;
            else l=mid;
        }
        vv[i]=(l+r)/2;
        sum+=s[i]*k[i]*(vv[i]-v[i])*(vv[i]-v[i]);
    }
    return sum;
}

int main()
{
    scanf("%d%lf",&n,&E);
    for(int i=1;i<=n;++i)
    {
        scanf("%lf%lf%lf",&s[i],&k[i],&v[i]);
        vmax[i]=s[i]>0?v[i]+sqrt(E/s[i]/k[i]):0;
    }

    double l=0, r=1e4, mid;
    while(r-l>eps)
    {
        mid=(l+r)/2;
        if(cal(mid)<E)r=mid;
        else l=mid;
    }
    double ans=0;
    for(int i=1;i<=n;++i)ans+=s[i]/vv[i];
    printf("%.10f\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值