题意为在满足(sumlimits_{i=1}^nk_i(v_i-v_i^prime)^2s_ileqslant E_U)的条件下最小化(sumlimits_{i=1}^nfrac{s_i}{v_i})
先考虑贪心,因为最小化(sumlimits_{i=1}^nfrac{s_i}{v_i}),所以(sumlimits_{i=1}^nk_i(v_i-v_i^prime)^2s_i=E_U)时为最优情况。
发现是一个有约束的极值问题,考虑用拉格朗日乘数法来解决。
设(f(v)=sumlimits_{i=1}^nfrac{s_i}{v_i}),(φ(v)=sumlimits_{i=1}^nk_i(v_i-v_i^prime)^2s_i-E_U)
设拉格朗日函数为(L(v,λ)=f(v)+λφ(v))
代入得(L(v,λ)=sumlimits_{i=1}^nfrac{s_i}{v_i}+λ[sumlimits_{i=1}^nk_i(v_i-v_i^prime)^2s_i-E_U])
根据拉格朗日乘数法得,当拉格朗日函数(L)梯度为(0)时,(f(v))最优
[egin{cases}
abla_{v_1}L(v,λ)=0\
abla_{v_2}L(v,λ)=0\......\
abla_{v_n}L(v,λ)=0\
abla_λL(v,λ)=0end{cases}
]
求偏导后可得(这里将有关(v)的写成一个式子了)
[egin{cases}
abla_vL(v,λ)=2λk_i(v_i-v_i^prime)s_i-frac{s_i}{v_i^2}=0\
abla_λL(v,λ)=sumlimits_{i=1}^nk_i(v_i-v_i^prime)^2s_i-E_U=0end{cases}
]
进一步化简后得
[egin{cases}2λk_iv_i^2(v_i-v_i^prime)=1 (1)\sumlimits_{i=1}^nk_i(v_i-v_i^prime)^2s_i=E_U (2)end{cases}
]
那么将上面的方程组解出来,即为我们要求的答案。
考虑到在((1))式中(v_i)必须大于等于(v_i^prime),所以为保证式子成立(λ)必须大于(0),同时发现((1))式左边关于(v_i)单调递增,所以我们二分求出每一个(v_i),再代入((1))式来检验。
但发现(λ)的值也不确定,于是要在二分(v_i)的外层再套上一层(λ)的二分,这里代入((2))式来检验。
实现细节看代码吧。
(code:)
#include<bits/stdc++.h>
#define maxn 10010
#define eps 1e-12
using namespace std;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
int n;
double E,ans;
double s[maxn],k[maxn],v[maxn],u[maxn];
double calc(double x)
{
return x*x;
}
bool judge(double p,double v,double k,double u)
{
return 2*p*k*calc(v)*(v-u)<=1;
}
bool check(double p)
{
double e=0;
for(int i=1;i<=n;++i)
{
double l=max(u[i],(double)0),r=1e5,ans;
while(l+eps<=r)
{
double mid=(l+r)/2.0;
if(judge(p,mid,k[i],u[i])) ans=l=mid;
else r=mid;
}
v[i]=ans;
e+=k[i]*calc(v[i]-u[i])*s[i];
}
return e<=E;
}
int main()
{
read(n);
scanf("%lf",&E);
for(int i=1;i<=n;++i)
scanf("%lf%lf%lf",&s[i],&k[i],&u[i]);
double l=0,r=1e5;
while(l+eps<=r)
{
double mid=(l+r)/2.0;
if(check(mid)) r=mid;
else l=mid;
}
for(int i=1;i<=n;++i) ans+=s[i]/v[i];
printf("%.8lf",ans);
return 0;
}