动态规划-叠塔问题

问题描述

给定 n n n 块积木,编号为 1 1 1 n n n。第 i i i 块积木的重量为 w i w_i wi( w i w_i wi 为整数),硬度为 s i s_i si,价值为 v i v_i vi
现要从中选择部分积木垂直摞成一座塔,要求每块积木满足如下条件:
若第 i i i 块积木在积木塔中,那么在其之上摆放的所有积木的重量之和不能超过第 i i i 块积木的硬度。
试设计算法求出满足上述条件的价值和最大的积木塔,输出摆放方案和最大价和。

算法思想

相关数学结论证明

先寻找能简化问题的数学结论:任意 k k k块积木,若存在能够堆叠成塔的方案,则可行方案中一定包含它们按 s i + w i s_i+w_i si+wi递增的顺序自上而下地堆叠的方案,且该方案一定是最优方案。这里的“最优”定义为:将 k k k块积木视为一个整体的承重能力最强。

  • 首先证明两块积木的情况:对两块积木 ( s 1 , w 1 ) , ( s 2 , w 2 ) (s_1,w_1),(s_2,w_2) (s1,w1),(s2,w2),不妨设 s 1 + w 1 ≤ s 2 + w 2 s_1+w_1\leq s_2+w_2 s1+w1s2+w2。若能堆叠成塔,一定有 s 1 ≥ w 2 s_1\geq w_2 s1w2 s 2 ≥ w 1 s_2\geq w_1 s2w1
    • 首先证明若能堆叠成塔,积木 2 2 2放下面一定是可行方案:
      • s 2 ≥ w 1 s_2\geq w_1 s2w1,已知积木 2 2 2能放在下面;
      • s 1 ≥ w 2 s_1\geq w_2 s1w2,则 w 2 + w 1 ≤ s 1 + w 1 ≤ s 2 + w 2 w_2+w_1\leq s_1+w_1\leq s_2+w_2 w2+w1s1+w1s2+w2,得 w 1 ≤ s 2 w_1\leq s_2 w1s2,即积木 2 2 2一定也能放在下面。得证。
    • 再证明积木 2 2 2放下面一定是最优方案:
      • 若积木 1 1 1放下面,两块积木作为一个整体的承重能力 s = m i n { s 2 , s 1 − w 2 } s=min\{s_2,s_1-w_2\} s=min{s2,s1w2}。注意 s 2 + w 2 ≥ s 1 + s 2 > s 1 s_2+w_2\geq s_1+s_2>s_1 s2+w2s1+s2>s1,有 s 2 > s 1 − w 2 s_2>s_1-w_2 s2>s1w2,故 s = s 1 − w 2 s=s_1-w_2 s=s1w2
      • 若积木 2 2 2放下面,两块积木作为一个整体的承重能力 s ′ = m i n { s 1 , s 2 − w 1 } s'=min\{s_1,s_2-w_1\} s=min{s1,s2w1}。注意 s 1 > s 1 − s 2 s_1>s_1-s_2 s1>s1s2 s 2 − w 1 ≥ s 1 − w 2 s_2-w_1\geq s_1-w_2 s2w1s1w2,故恒有 s ′ ≥ s s'\geq s ss。得证。
  • 再证明对于 k k k块积木结论也成立:假设这 k k k块积木存在能够成塔的方案,对于方案中任意上下相邻的两块积木 i , j i,j i,j,如果 s i + w i > s j + w j s_i+w_i> s_j+w_j si+wi>sj+wj,由上面两块积木情况的结论,将它们交换顺序后,两块积木之间一定仍符合承重要求,而对外的承重能力也一定不会减少,因此 k k k块积木一定也仍能成塔。基于此,我们从上往下依次检查相邻的积木对,若不符合 s i + w i ≤ s j + w j s_i+w_i\leq s_j+w_j si+wisj+wj则交换顺序。如此重复进行
    k − 1 k-1 k1轮,第 l l l轮检查范围为 1 1 1~ n − l + 1 n-l+1 nl+1块。最终得到的堆叠方案也一定是可行的,且其作为一个整体的承重能力最强。这一过程类似于冒泡排序,最终得到的方案一定是按 s i + w i s_i+w_i si+wi递增的顺序排列的。命题得证。

动态规划

先将所有积木按 s i + w i s_i+w_i si+wi升序排序,简便起见,仍记排序后的积木为 ( s 1 , w 1 ) , ( s 2 , w 2 ) , . . . , ( s n , w n ) (s_1,w_1),(s_2,w_2),...,(s_n,w_n) (s1,w1),(s2,w2),...,(sn,wn)

采用动态规划的思想,将“求前 i i i块积木的最大价值和 d p [ i ] dp[i] dp[i]”的问题转化为一系列求前 i − 1 i-1 i1块积木摆放方案和最大价值和的问题。为了便于求解,为递推的变量增加“总重量为 W W W”的约束维度。则总重量为 W W W的前 i i i块积木的最大价值 d p [ i ] [ W ] dp[i][W] dp[i][W]可能由以下情况达到:

  • 能够包含第 i i i块积木: d p [ i ] [ W ] = m a x { d p [ i − 1 ] [ W − w i ] + v i , d p [ i − 1 ] [ W ] } dp[i][W]=max\{dp[i-1][W-w_i]+v_i, dp[i-1][W]\} dp[i][W]=max{dp[i1][Wwi]+vi,dp[i1][W]}。由上述数学结论,第 i i i块积木能作为塔的一部分,当且仅当它能够作为塔的最底部,即 s i ≥ W − w i s_i\geq W-w_i siWwi
  • 不能够包含第 i i i块积木, d p [ i ] [ W ] = d p [ i − 1 ] [ W ] dp[i][W]=dp[i-1][W] dp[i][W]=dp[i1][W]。由上述数学结论,此时 s i < W − w i s_i<W-w_i si<Wwi

综上,状态转移方程为:
d p [ i ] [ W ] = { m a x { d p [ i − 1 ] [ W − w i ] + v i , d p [ i − 1 ] [ W ] } , s i ≥ W − w i d p [ i − 1 ] [ W ] , s i ≥ W − w i dp[i][W]= \begin{cases} max\{dp[i-1][W-w_i]+v_i, dp[i-1][W]\},s_i\geq W-w_i\\ dp[i-1][W],s_i\geq W-w_i \end{cases} dp[i][W]={max{dp[i1][Wwi]+vi,dp[i1][W]}siWwidp[i1][W]siWwi

每次转移的时间复杂度为 O ( 1 ) O(1) O(1)

此外,还要设计追踪数组 t r a c k [ 1 , . . . , n ] [ ] track[1,...,n][] track[1,...,n][],记录每块积木是否入选。

伪代码

在这里插入图片描述

时间复杂度分析

  • 排序的复杂度最小为 O ( n l o g n ) O(nlogn) O(nlogn)
  • 每次转移的复杂度为 O ( 1 ) O(1) O(1),共两层循环,外层为 n n n次,而内层循环的最坏情况为 ∑ i = 1 n w i \sum\limits_{i=1}^{n}w_i i=1nwi次,故填表的复杂度为 O ( n ∑ i = 1 n w i ) O(n\sum\limits_{i=1}^{n}w_i) O(ni=1nwi)

显然, ∑ i = 1 n w i > l o g n \sum\limits_{i=1}^{n}w_i>logn i=1nwi>logn,故总复杂度为 O ( n ∑ i = 1 n w i ) O(n\sum\limits_{i=1}^{n}w_i) O(ni=1nwi)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值