zoukankan      html  css  js  c++  java
  • 拉格朗日乘数法

    luogu2179 [NOI2012]骑行川藏

    虽然我并不知道如何证明,但是背下结论套的话这题就是模板题了。

    设第$i$段路骑行速度为$x_i$

    $f=sum frac{s_i}{x_i}$

    要求最小化$f$

    设$g=E_u-sum k_i*(x_i-v_i)^2*s_i$

    贪心,当$x_i<v_i$时,存在关于$v_i$对称的$x$使代价不变而答案更优
    故$x_i>=v_i$

    故当$g$不为0时,一定可以增大$x$使答案更优,即最优解时$g=0$

    $f=sum frac{s_i}{x_i}$

    $g=E_u-sum k_i*(x_i-v_i)^2*s_i=0$

    设$t=f-lambda*g$

    根据拉格朗日乘数啥子的,当$t$的偏导为$0$时,$f$取得极值


    $-frac{s_i}{x_i}+ 2lambda k_i s_i(x_i-v_i)=0$

    $x_i>=v_i$,故$lambda$随$x_i$单调

    二分$lambda$使$g=0$即可

    注意实数二分最好控制次数而不是$eps$

    关于二分的上界我比较懵逼,我看有人开到1e5就过了,这个大概要随缘吧……

     1 //Achen
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<vector>
     7 #include<cstdio>
     8 #include<queue>
     9 #include<cmath>
    10 #include<set>
    11 #include<map>
    12 #define Formylove return 0
    13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
    14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
    15 #define eps 1e-15
    16 const int N=1e4+7;
    17 typedef long long LL;
    18 typedef double db;
    19 using namespace std;
    20 int n;
    21 db E,s[N],k[N],v[N],x[N];
    22 
    23 template<typename T>void read(T &x)  {
    24     char ch=getchar(); x=0; T f=1;
    25     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    26     if(ch=='-') f=-1,ch=getchar();
    27     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    28 }
    29 
    30 int dcmp(db x) { return fabs(x)<=eps?0:(x>0?1:-1); }
    31 
    32 void get_x(db lmd) {
    33     lmd=1.0/lmd;
    34     For(i,1,n) {
    35         db l=max(0.0,v[i]),r=1e5;
    36         For(ti,1,80) {
    37             db mid=(l+r)/2.0;
    38             if(dcmp(k[i]*mid*mid*2*(mid-v[i])-lmd)<=0) l=mid;
    39             else r=mid;
    40         }
    41         x[i]=l;
    42     }
    43 }
    44 
    45 int ck(db lmd) {
    46     get_x(lmd);
    47     db tp=E;
    48     For(i,1,n) 
    49         tp-=k[i]*(x[i]-v[i])*(x[i]-v[i])*s[i];
    50     return dcmp(tp)>=0;
    51 }
    52 
    53 int main() {
    54 #ifdef ANS
    55     freopen(".in","r",stdin);
    56     freopen(".out","w",stdout);
    57 #endif
    58     read(n);
    59     scanf("%lf",&E); 
    60     For(i,1,n) 
    61         scanf("%lf %lf %lf",&s[i],&k[i],&v[i]);
    62     db l=0,r=1e5,lmd;
    63     For(ti,1,80) {
    64         lmd=(l+r)/2.0;
    65         if(ck(lmd)) r=lmd;
    66         else l=lmd;
    67     }
    68     get_x(lmd);
    69     db ans=0;
    70     For(i,1,n) ans+=s[i]/x[i];
    71     printf("%.6lf
    ",ans);
    72     Formylove;
    73 }
    View Code

    yja

    和上道题一样的模板

  • 相关阅读:
    iOS开发UI篇—UIScrollView控件介绍
    iOS开发UI篇—iOS开发中三种简单的动画设置
    iOS开发UI篇—iOS开发中Xcode的一些使用技巧
    iOS开发UI篇—在ImageView中添加按钮以及Tag的参数说明
    iOS开发UI篇—KVC简单介绍
    iOS开发UI篇—从代码的逐步优化看MVC
    iOS开发UI篇—xib的简单使用
    iOS开发UI篇—字典转模型
    iOS开发UI篇—九宫格坐标计算
    A1005. Spell It Right
  • 原文地址:https://www.cnblogs.com/Achenchen/p/9527723.html
Copyright © 2011-2022 走看看