【斜率优化】[CEOI2004]锯木厂选址——从这里开始斜率优化的大门

题目

好久没有碰过斜率优化了,我们从这里来开始复习一下, 先看一下题目:
从山顶上到山底下沿着一条直线种植了n棵老树。当地的政府决定把他们砍下来。为了不浪费任何一棵木材,树被砍倒后要运送到锯木厂。木材只能按照一个方向运输:朝山下运。山脚下有一个锯木厂。另外两个锯木厂将新修建在山路上。你必须决定在哪里修建两个锯木厂,使得传输的费用总和最小。假定运输每公斤木材每米需要一分钱。

题目解析

定义:
wi 为第 i 个位置上的树的重量, n为山坡的长度, di 为第 i 棵树和第i+1棵树之间的距离,我们令 Sd(i)=i1j=1di (这里使用 i1 )是因为第 1(i1) 为到第 i 棵树木距离,Sw(i)=ij=1wj
首先我们先看一看这种题目我们一般是怎么处理的: g(i) 表示在i处修建第一个伐木场那么要从第 i1 1 的树木全部运到我们所需要的代价,那么我们可以发现

g(i)=g(i1)+di1×Swi1
那么同时我们令 f(j,i) 表示当我们第二个伐木场修建在 i ,第一个修在j时我们可以得到的最优解我们令 cost(j,i) 表示将 j i全部运到 i 我们需要的代价那么
cost(j,i)=g(i)Sdi×Swj1
那么我们可以得到

f(j,i)=g(j)+cost(j+1,i)+cost(i+1,n)
那么我们可以表示两个决策点,对于当前的 i 我们有两种选择方案选择第一个伐木场第一种f(j,i)第二种 f(k,i) 如果有j的决策点优于k的决策点且
j<k
那么我们就有
f(j,i)<f(k,i)f(k,i)f(j,i)>0[g(k)+cost(k+1,i)][g(j)+cost(j+1,i)]>0g(k)g(j)+cost(k+1,i)cost(j+1,i)>0g(k)g(j)Sdi×Swk+Sdi×Swj>0g(k)g(j)>Sdi(SwkSwj)g(k)g(j)SwkSwj>Sdi
这个式子我们称为斜率式那么我们就得到 i 决策点的坐标为(Swi,g(i))那么我们可以发现当斜率满足上述的条件的时候我们的最优解就应该选择 j 节点了但是我们并不能立刻抛弃k因为 Sdi 是单调递增的那么如果当前两点的斜率小于了我们就要将 j 扔掉,可以发现我们需要维护该队列中的保持单调递增理由如下:

维护

假设我们现在需要加入一个点i使得队列队尾元素为 j<k 那么我们有如果 K(j,k)>Sdi 那么我们现在最优解肯定不是 k 那么如果我们K(k,i)<K(j,k)那么我们需要将k弹出因为这样就可以保证 K(j,i)>K(k,i) 那么我们 j 的可接受范围就更广了并且显然大于k的范围,那么这就是队尾为什么要这样维护:如果我们发现当前 K(j,k)>K(k,i) 那么如果 K(j,k)<Sdi 那么 K(k,i) 也会小于 Sdi 那么我们就可以发现 k <script type="math/tex" id="MathJax-Element-16463">k</script>无论如何都是选择不到的
队首我们需要维护一下上面的不等式,最后每一次从队首取出当前的最优决策点进行计算,最终就得到答案
(因为满足上面的性质,所以其实每一个不同情况的最优决策点也是递增的(Sd_i递增))所以我们只可能从前pop(j)而不会从前面压入任何一个使用过的节点。
代码我就先不写了

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值