欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

【斜率优化】仓库建设(luogu 2120)

发布时间:2023/12/3 编程问答 49 豆豆
生活随笔 收集整理的这篇文章主要介绍了 【斜率优化】仓库建设(luogu 2120) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

仓库建设

luogu 2120

题目大意

有一个斜坡,上面有n个工厂(山顶是1,山脚是nnn,工厂都是漏填),上面有pip_ipi个货物,和工厂1的距离为x1x_1x1
现在有一场大雨,你可以在某些工厂处建立仓库(费用是cic_ici),没有建立仓库的工厂要把货物运到更低的仓库(及编号越大的仓库),运费是货物数∗*距离
现在问你全部货物运到仓库中最少需要多少钱

输入样例

3 0 5 10 5 3 100 9 6 10

输出样例

32

样例说明

在工厂 1 和工厂 3 建立仓库,建立费用为 10+10=2010+10=2010+10=20 ,运输费用为 (9−5)×3=12(9-5) \times 3 = 12(95)×3=12,总费用 32。

数据范围

对于 20%20\%20% 的数据,保证 n≤500n \leq 500n500
对于 40%40\%40% 的数据,保证 n≤104n \leq 10^4n104
对于 100%100\%100% 的数据,保证 1≤n≤1061 \leq n \leq 10^61n1060≤xi,pi,ci<2310 \leq x_i,~p_i,~c_i < 2^{31}0xi, pi, ci<231
对于任意的 1≤i<n1 \leq i < n1i<n,保证 xi<xi+1。x_i < x_{i + 1} 。xi<xi+1
设答案为 ansansans,保证 ans+∑i=1npixi<263ans + \sum_{i = 1}^{n} p_ix_i < 2^{63}ans+i=1npixi<263

解题思路

我们设fif_ifi为在iii处建仓库,前iii个工厂的货物全部运到仓库的最小费用(这里把ppp改为sss,把xxx改为vvv
我们就可以得出转移方程
fi=min⁡{fj+ci+∑k=j+1i−1(vi−vk)sk}=min⁡{fj+ci+∑k=j+1i(vi−vk)sk}=min⁡{fj+ci+∑k=j+1ivisk−∑k=j+1ivksk}=min⁡{fj+ci+(sumsi−sumsj)vi−(vsi−vsj)}\begin{aligned}f_i & = \min\{f_j+c_i+\sum_{k=j+1}^{i-1}(v_i-v_k)s_k\} \\ & = \min\{f_j+c_i+\sum_{k=j+1}^{i}(v_i-v_k)s_k\} \\ & =\min\{f_j+c_i+\sum_{k=j+1}^{i}v_is_k-\sum_{k=j+1}^{i}v_ks_k\} \\ & = \min\{f_j + c_i + (sums_i-sums_j)v_i - (vs_i - vs_j)\} \end{aligned}fi=min{fj+ci+k=j+1i1(vivk)sk}=min{fj+ci+k=j+1i(vivk)sk}=min{fj+ci+k=j+1iviskk=j+1ivksk}=min{fj+ci+(sumsisumsj)vi(vsivsj)}
注:
第二行加了iii这一项,但因为vi−vi=0v_i-v_i=0vivi=0所以结果不变
第四行vsi=∑j=1ivisivs_i=\sum_{j=1}^{i} v_is_ivsi=j=1ivisi
若现在有两个决策点a,ba,ba,b满足a>b,aa>b,aa>b,a优于bbb
则:
fa+ci+(sumsi−sumsa)vi−(vsi−vsa)<fb+ci+(sumsi−sumsb)vi−(vsi−vsb)f_a + c_i + (sums_i-sums_a)v_i - (vs_i - vs_a) < f_b + c_i + (sums_i-sums_b)v_i - (vs_i - vs_b)fa+ci+(sumsisumsa)vi(vsivsa)<fb+ci+(sumsisumsb)vi(vsivsb)
fa+ci+sumsivi−sumsavi−vsi+vsa<fb+ci+sumsivi−sumsbvi−vsi+vsbf_a + c_i + sums_iv_i-sums_av_i - vs_i + vs_a < f_b + c_i + sums_iv_i-sums_bv_i - vs_i + vs_bfa+ci+sumsivisumsavivsi+vsa<fb+ci+sumsivisumsbvivsi+vsb
fa−sumsavi+vsa<fb−sumsbvi+vsbf_a-sums_av_i + vs_a < f_b-sums_bv_i + vs_bfasumsavi+vsa<fbsumsbvi+vsb
(fa+vsa)−(fb+vsb)<sumsavi−sumsbvi(f_a+vs_a)-(f_b+vs_b)< sums_av_i-sums_bv_i(fa+vsa)(fb+vsb)<sumsavisumsbvi
(fa+vsa)−(fb+vsb)<sumsavi−sumsbvi(f_a+vs_a)-(f_b+vs_b)< sums_av_i-sums_bv_i(fa+vsa)(fb+vsb)<sumsavisumsbvi
((fa+vsa)−(fb+vsb))/(sumsa−sumsb)<vi((f_a+vs_a)-(f_b+vs_b))/(sums_a-sums_b)<v_i((fa+vsa)(fb+vsb))/(sumsasumsb)<vi
我们设
yi=fi+vsay_i=f_i+vs_ayi=fi+vsa
xi=sumsix_i=sums_ixi=sumsi

(ya−yb)/(xa−xb)<vi(y_a-y_b)/(x_a-x_b)<v_i(yayb)/(xaxb)<vi
然后按照斜率优化模板套即可

代码

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long using namespace std; ll n, l, r, v[1000050], s[1000050], c[1000050], d[1000050], y[1000050], f[1000050], vs[1000050]; int main() {scanf("%d", &n);for (int i = 1; i <= n; ++i){scanf("%d%d%d", &v[i], &s[i], &c[i]);vs[i] = vs[i - 1] + v[i] * s[i];s[i] += s[i - 1];//s没用,就直接弄成前缀和}for (int i = 1; i <= n; ++i){while(r > l && (y[d[l + 1]] - y[d[l]]) < v[i] * (s[d[l + 1]] - s[d[l]])) l++;//模板f[i] = f[d[l]] + c[i] + (s[i] - s[d[l]]) * v[i] - (vs[i] - vs[d[l]]);y[i] = f[i] + vs[i];while(r > l && (y[i] - y[d[r]])*(s[d[r]] - s[d[r-1]]) < (y[d[r]] - y[d[r-1]])*(s[i] - s[d[r]])) r--;d[++r] = i;}printf("%d", f[n]);return 0; }

总结

以上是生活随笔为你收集整理的【斜率优化】仓库建设(luogu 2120)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。