题意:给定E s v' k,求v最小化$\sum\limits_{i = 1}^N {\frac{{{s_i}}}{{{v_i}}}}$,要求$\sum\limits_{i = 1}^N {{k_i}{s_i}{{\left( {{v_i} - v_i^'} \right)}^2}} \le E$
题解:
设每一段使用的E为Ei,用E替出v得到\[{v_i} = v_i^' + \sqrt {\frac{{{E_i}}}{{{k_i}{s_i}}}} \Rightarrow {t_i} = \frac{{{s_i}}}{{v_i^' + \sqrt {\frac{{{E_i}}}{{{k_i}{s_i}}}} }}\]
由于要求t的和最小,因此E要尽量大,则一定有\[\sum\limits_{i = 1}^N {{k_i}{s_i}{{\left( {{v_i} - v_i^'} \right)}^2}} = E\]
设\[F = \sum\limits_{i = 1}^N {\frac{{{s_i}}}{{{v_i}}}} + \lambda \sum\limits_{i = 1}^N {{k_i}{s_i}{{\left( {{v_i} - v_i^'} \right)}^2}} \]
由拉格朗日乘子法,F对xi求偏导得$$ - \frac{{{s_i}}}{{{v_i}}} + 2\lambda {k_i}{s_i}\left( {{v_i} - v_i^'} \right) = 0 \Rightarrow 2\lambda {k_i}{s_i}v_i^2\left( {{v_i} - v_i^'} \right) = 0$$
与关于E的等式联立发现v的增大受E限制,同时与$\lambda$成反比,因此我们二分$\lambda$,看得到的E是否合法,每次二分把v全部算出来
#include <cmath> #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; #define INF 1e8 #define eps 1e-12 const int MAXN=10000+2; int N; double E,s[MAXN],k[MAXN],v[MAXN],x[MAXN],ans; double Calc(double t){ double ret=0; for(int i=1;i<=N;i++){ double l=0,r=INF,m; while(r-l>eps){ m=(l+r)/2; if(2*t*k[i]*m*m*(m-v[i])>1) r=m; else l=m; } x[i]=(l+r)/2,ret+=k[i]*(x[i]-v[i])*(x[i]-v[i])*s[i]; } return ret; } int main(){ scanf("%d %lf",&N,&E); for(int i=1;i<=N;i++) scanf("%lf %lf %lf",s+i,k+i,v+i); double l=0,r=INF,m; while(r-l>eps){ m=(l+r)/2; if(Calc(m)>=E) l=m; else r=m; } for(int i=1;i<=N;i++) ans+=s[i]/x[i]; printf("%.8lf\n",ans); return 0; }