钢条切割问题

"""
1.设长度为n的钢条切割后最优收益值为rn,可以得出递推式:rn = max(pn, r1 + rn-1,r2+rn-2,..., rn-1+r1)
2.第一个参数Pn表示不切割
3.其他n-1个参数分别表示另外n-1种不同切割方案,对方案i=1,2,...,n-1
  3.1.将钢条切割为长度为i和n-i两段
  3.2.方案i的收益为切割两段的最优收益之和
4.考察所有的i,选择其中收益最大的方案
"""

"""
钢条切割问题--最优子结构
1、可以将求解规模为n的原问题,划分为规模更小的子问题:完成一次切割后,可以将产生的两段钢条看成两个独立的钢条切割问题
2、组合两个子问题的最优解,并在所有可能的两段切割方案中选取组合收益最大的,构成原问题的最优解
3、钢条切割满足最优子结构:问题的最优解由相关子问题的最优解组合而成,这些子问题可以独立求解
"""

"""
钢条切割问题还存在更简单的递归求解方法(这里有疑问)
1、从钢条的左边切割下长度为i的一段,只对右边剩下的一段继续进行切割,左边的不再切割(为啥?)
2、递推式简化为rn = max 1<=i<=n(pi + rn-i)
3、不做切割的方案就可以描述为:左边一段长度为n,收益为Pn,剩余一段长度为0,收益为r0 = 0
"""

p = [0, 1, 5, 8, 9, 10, 17, 17, 20, 21, 23, 24, 26, 27, 27, 28, 30, 33, 36, 39, 40]

# p = [0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30]

def cut_rod_recurision_1(p, n):
    if n == 0:
        return 0
    else:
        res = p[n]
        for i in range(1, n):
            res = max(res, cut_rod_recurision_1(p, i) + cut_rod_recurision_1(p, n - i))
        return res


print(cut_rod_recurision_1(p, 20))

# 自顶向下递归实现
def cut_rod_recurision_2(p, n):
    if n == 0:
        return 0
    else:
        res = 0
        for i in range(1, n + 1):
            res = max(res, p[i] + cut_rod_recurision_2(p, n - i))
        return res


print(cut_rod_recurision_2(p, 20))

"""
钢条切割问题--动态规划解法
1、递归算法由于重复求解相同子问题,效率极低
2、动态规划的思想:
    2.1、每个问题只求解一次,保存求解结果
    2.2、之后需要此问题时,只需查找保存的结果
"""

def cut_rod_dp(p, n):
    r = [0]
    for i in range(1, n + 1):
        res = 0
        for j in range(1, i + 1):
            res = max(res, p[j] + r[i - j])
        r.append(res)
    return r[n]


print(cut_rod_dp(p, 20))

"""
如何修改动态规划算法,使其不仅输出最优解,还输出最优切割方案?
对每个子问题,保存切割一次时左边切下的长度
"""


def cut_rod_extend(p, n):
    r = [0]
    s = [0]
    for i in range(1, n + 1):
        res_r = 0  # 价格的最大值
        res_s = 0  # 价格最大值对应方案的左边不切割部分的长度
        for j in range(1, i + 1):
            if p[j] + r[i - j] > res_r:
                res_r = p[j] + r[i - j]
                res_s = j
        r.append(res_r)
        s.append(res_s)
    return r[n], s


def cut_rod_solution(p, n):
    r, s = cut_rod_extend(p, n)
    ans = []
    while n > 0:
        ans.append(s[n])
        n -= s[n]
    return r, ans


print(cut_rod_solution(p, 20))


"""
动态规划问题关键特征
1、什么问题可以使用动态规划?
比如:
1.1、最优子结构
    1.1.1、原问题的最优解中涉及多少个子问题
    1.1.2、在确定最优解使用哪些子问题时,需要考虑多少种选择
1.2、重叠子问题
"""

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值