「NOI2012」骑行川藏

这道题被 yhx-12243 吐槽,但是我还是没考虑全所有的细节……

这种数学题也是要尽量去推条件的。


这道题精度要求貌似很高……还是我写丑了?

根据题意,可以列出式子

\[\mathrm{Minimize} \sum \frac{s_i}{v_i} \\ \mathrm{s.t.} \sum k_i s_i \left(v_i - v_i'\right)^2 = E \]

多元函数求最值,考虑拉格朗日乘数

\[\begin{align*} g(v) & = \sum k_i s_i \left(v_i - v_i'\right)^2 - E \\ f(v, \lambda) & = \sum \frac{s_i}{v_i} + \lambda g(v) \end{align*} \]

解方程

\[\begin{align*} \frac{\partial f(v, \lambda)}{\partial v_i} & = - \frac{s_i}{v_i^2} + 2 \lambda k_i s_i \left(v_i - v_i'\right)^2 & = 0\\ \frac{\partial f(v, \lambda)}{\partial \lambda} & = \sum k_i s_i \left(v_i - v_i'\right)^2 - E & = 0 \end{align*} \]

对于 \(v_i\) 的偏导,发现 \(2 \lambda k_i \left(v_i - v_i'\right)^2 = 1\)

注意到如果我们的速度 \(v_i > v_i'\)。如果 \(v_i < v_i'\),那么存在一个 \(v = 2v_i' - v_i\),那么能量消耗相等,但是速度更快了,明显更优。

于是将这个条件带入方程,发现 \(\lambda > 0\)

然后发现当 \(\lambda\) 增大, \(v_i\) 是单调减的。那么 \(g(v)\) 也会单调减。所以可以二分 \(\lambda\) 来找到一个满足第二条方程式的解

然后将得到的解带入就好了。

关于解出 \(v_i\),可以二分,也可以迭代。注意迭代的初始解要大,不然会挂。

注意调参,在精度与速度中权衡。如果没写挂也不会爆 nan 的。

复杂度 \(O\left( k_1k_2n \right)\),其中 \(k_1\)\(\lambda\) 二分次数, \(k_2\) 是解方程迭代次数。

#include <bits/stdc++.h>

const int MAXN = 10010;
const int STP = 30;
const int S2 = 150;
typedef long double ld;
const ld eps = 1e-12;
ld ss[MAXN], ks[MAXN], vs[MAXN];
int n; ld E;
ld solve(int i, ld l) {
	ld x = 1e5;
	ld c = .5 / ks[i] * l;
	for (int S = 0; S < STP; ++S) {
		ld func = x * x * (x - vs[i]) - c;
		ld de = x * (3 * x - 2 * vs[i]);
		x -= func / de;
	}
	return x;
}
ld tv[MAXN];
inline ld pows(ld x) { return x * x; }
int main() {
	std::ios_base::sync_with_stdio(false), std::cin.tie(0);
	std::cin >> n >> E;
	for (int i = 1; i <= n; ++i) std::cin >> ss[i] >> ks[i] >> vs[i];
	ld l = 0, r = 1e10;
	for (int S = 1; S <= S2; ++S) {
		ld mid = (l + r) / 2;
		ld sum = 0;
		for (int i = 1; i <= n; ++i) {
			tv[i] = solve(i, mid);
			sum += ks[i] * ss[i] * pows(tv[i] - vs[i]);
		}
		sum > E ? r = mid : l = mid;
	}
	ld ans = 0;
	for (int i = 1; i <= n; ++i) ans += ss[i] / tv[i];
	std::cout << std::fixed << std::setprecision(10) << ans << std::endl;
	return 0;
}
posted @ 2019-10-10 15:06  daklqw  阅读(172)  评论(0编辑  收藏  举报