在满足 ∑ni=1siki(xi−vi)2≤EU ∑ 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(xi−vi)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(xi−vi)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
在这题里面
可以看出 λ λ 是关于 xi x i 的函数是一个单调函数(不然没法求啊)
而且由于 xi x i 一定要大于 vi v i
(如果 xi<vi x i < v i ,根据 g g 的式子可以看出一定可以找到一个对称的 x′i 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;
}