卧薪尝胆,厚积薄发。
NOI2012 骑行川藏
Date: Thu Dec 13 19:32:24 CST 2018
In Category:
NoCategory
Description:
给出
$k_i,s_i,v_i$
,并要求:
$$
\sum_{i=1}^nk_i(x_i-v_i)^2s_i\leqslant E
$$
最大化:
$$
f(x_1,x_2,\dots,x_n)=\sum_{i=1}^n\frac{s_i}{x_i}
$$
$1\leqslant n\leqslant 10^4$
Solution:
首先那个不等号一定是要取等的,不然一定不优。
套用拉格朗日乘数法,设:
$$
\varphi(x_1,x_2,\dots,x_n)=\sum_{i=1}^nk_i(x_i-v_i)^2s_i-E=0
$$
然后设拉格朗日函数:
$$
L(x_1,x_2,\dots,x_n)=f(x_1,x_2,\dots,x_n)-\lambda\varphi(x_1,x_2,\dots,x_n)
$$
分别对
$x_1,x_2,\dots,x_n,\lambda$
在拉格朗日函数上求偏导,那么极值点就是所有的偏导数取
$0$
的点。
对于这题:
$$
L(x_1,x_2,\dots,x_n)=\sum_{i=1}^n\frac{s_i}{x_i}-\lambda\sum_{i=1}^nk_i(x_i-v_i)^2s_i
$$
对
$\lambda$
求偏导显然就是:
$$
\varphi(x_1,x_2,\dots,x_n)=\sum_{i=1}^nk_i(x_i-v_i)^2s_i-E=0
$$
对
$x_i$
求偏导:
$$
\begin{align}
L'(x_i)=(\frac{s_i}{x_i})'+(\lambda k_i(x_i-v_i)^2s_i)'&=0\\
-s_ix_i^{-2}+2\lambda k_is_i(x_i-v_i)&=0\\
2\lambda x_i^2k_i(x_i-v_i)=1
\end{align}
$$
现在考虑怎么解这
$n+1$
个方程,首先所有的
$x_i$
都应大于
$v_i$
,否则一定不优,那么
$x_i^2(x_i-v_i)$
就是单调的,如果
$\lambda$
确定了,我们就可以二分得到
$x_i$
,
$\lambda$
越大,
$x_i$
越小,
$\varphi$
越小,也就是说我们可以再在外面套一个
$\lambda$
的二分即可。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
int n;double E;
#define MAXN 10010
double s[MAXN],k[MAXN],v[MAXN];
double x[MAXN];
double calc(double lambda)
{
for(int i = 1;i <= n;++i)
{
double l = v[i],r = 1000000,mid;
for(int w = 1;w <= 80;++w)
{
mid = (l + r) / 2;
if(2 * lambda * mid * mid * k[i] * (mid - v[i]) > 1)r = mid;
else l = mid;
}
x[i] = l;
}
double sum = 0;
for(int i = 1;i <= n;++i)
{
sum = sum + k[i] * (x[i] - v[i]) * (x[i] - v[i]) * s[i];
}
return sum;
}
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 = 1000000,mid;
for(int i = 1;i <= 80;++i)
{
mid = (l + r) / 2;
if(calc(mid) - E < 0)r = mid;
else l = mid;
}
calc(l);
double ans = 0;
for(int i = 1;i <= n;++i)
{
ans = ans + s[i] / x[i];
}
printf("%.10lf\n",ans);
return 0;
}
In tag:
数学-拉格朗日乘数法
Copyright © 2020
wjh15101051
ღゝ◡╹)ノ♡