[NOI2012]骑行川藏

题意

在满足 ni=1siki(xivi)2EU ∑ i = 1 n s i k i ( x i − v i ) 2 ≤ E U 的条件下最小化 ni=1sixi ∑ i = 1 n s i x i


题解

可以贪心地想一定是当 ni=1siki(xivi)2=EU ∑ i = 1 n s i k i ( x i − v i ) 2 = E U 时最优

因为如果小于的话那么某个 xi x i 还可以大一点,使得答案更小

有限制的条件极值通常用拉格朗日乘数法来解决

f(x1,,xn)=ni=1sixi,g(x1,,xn)=ni=1siki(xivi)2=EU f ( x 1 , … , x n ) = ∑ i = 1 n s i x i , g ( x 1 , … , x n ) = ∑ i = 1 n s i k i ( x i − v i ) 2 = E U

在这题里面

f+λgxi=six2i+2λsiki(xivi)=0 ∂ f + λ g ∂ x i = − s i x i 2 + 2 λ s i k i ( x i − v i ) = 0

2λki(xivi)x2i1=0 ⇒ 2 λ k i ( x i − v i ) x i 2 − 1 = 0

λ=12ki(xivi)x2i ⇒ λ = 1 2 k i ( x i − v i ) x i 2

可以看出 λ λ 是关于 xi x i 的函数是一个单调函数(不然没法求啊)

而且由于 xi x i 一定要大于 vi v i

(如果 xi<vi x i < v i ,根据 g g 的式子可以看出一定可以找到一个对称的 xi x i ′ 使得答案更优,且不超过限制)

可以认为 g g 关于 xi x i 单调递增,即关于 λ λ 单调递减

所以我们可以二分 λ λ ,然后再解出 xi x i

这是一个关于 xi x i 的单调递增的函数

所以解 xi x i 的方法可以用二分法或者牛顿迭代法

#include
#define fp(i,a,b) for(register int i=a,I=b+1;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 a1: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=1e4+5;
const double eps=1e-13,inf=1e5;
typedef double d;
int n;d Eu,ans,s[N],k[N],x[N],v[N];
inline d sqr(const d a){return a*a;}
inline d bf(const int i,const d lb){
    d L=max(v[i],0.0),R=inf,mid;
    while(R-L>eps){
        mid=(L+R)*0.5;
        if(lb*k[i]*(mid-v[i])*sqr(mid)>1)R=mid;
        else L=mid;
    }return L;
}
inline bool chk(const d la){
    d tp=0;
    fp(i,1,n)x[i]=bf(i,la);
    fp(i,1,n)tp+=k[i]*sqr(x[i]-v[i])*s[i];
    return tpint main(){
    #ifndef ONLINE_JUDGE
        file("s");
    #endif
    scanf("%d%lf",&n,&Eu);
    fp(i,1,n)scanf("%lf%lf%lf",s+i,k+i,v+i);
    d L=0,R=inf,mid;
    while(R-L>eps){
        mid=(L+R)*0.5;
        if(chk(2*mid))R=mid;
        else L=mid;
    }
    fp(i,1,n)ans+=s[i]/x[i];
    printf("%.6lf",ans);
return 0;
}

你可能感兴趣的:(二分答案,数学,拉格朗日乘数法)