其他分享
首页 > 其他分享> > 钢条切割问题

钢条切割问题

作者:互联网


title: 钢条切割问题
date: 2022-05-10 20:42:52
tags: 动态规划

钢条切割问题

问题背景

现在有一个长度为10的钢条,可以零成本将其切割成多段长度更小的钢条,我们先要求出最大收益

钢条长度 0 1 2 3 4 5 6 7 8 9 10
价格p 0 1 5 8 9 10 17 17 20 24 24

如果我们不切割的话可以获得的最大收益为 24

如果我们按照 2 2 6 切割方法,收益为 27

所以不同的切割方法收益不同,我们寻求的就是收益最大的切割方法

问题定义

输入:

输出:

问题观察

  1. 假设钢条能够至多切割一次:有以下这几种情况

    image-20220510213417519

    我们就需要从这几种切割情况中寻找出收益最大的,max{p[i] + p[10-i], p[10]}

  2. 如果钢条能够切割两次:

    我们可以现将钢条切割出一段

    然后再剩余的钢条中继续切割

    image-20220510213630010

    这时候 长度为8的就可以看做切割次数为一的那一种情况

​ 这里可能存在最优子结构重叠子问题

问题结构分析

问题表示:

C[j]:切割长度为j的钢条可得到的最大总收益

递推关系的建立

image-20220510215011452

C[j] = Max{p[i] + C[j-i], p[j]}

C[j] 表示从这j种情况中选出最大的哪一种

这里面就存在最优子结构问题

自底向上的计算

我们通过 C[0] = 0这种情况来推断整个C数组

以后C[j] 的求导需要 依托于 C[1] ~ C[j - i] 这么多种情况中的最优解来进行C[j]的求解

所以这是一种区间性动态规划,每走一步都要依赖于一个区间的最优值

最优方案追踪

image-20220510220540284

递归出口:输出的钢条长度为n

算法实例

钢条长度 0 1 2 3 4 5 6 7 8 9 10
价格p 0 1 5 8 9 10 17 17 20 24 24
  1. 我们先初始化C[0] = 0
i 0 1 2 3 4 5 6 7 8 9 10
C[i] 0
rec 0
  1. 钢条长度为1

    这时候没得选只能够选择1

i 1
1
i 0 1 2 3 4 5 6 7 8 9 10
C[i] 0 1
rec 0 1 2 3 4 5 6 7 8 9 10
1
  1. 钢条长度为2:

​ 有两种情况

从上面选择情况最大的:不切割

i 1 2
2 5
i 0 1 2 3 4 5 6 7 8 9 10
C[i] 0 1 5
rec 0 1 2 3 4 5 6 7 8 9 10
1 2
  1. 钢条长度为3:

​ 有三种情况:

从上面选择情况最大的:不切割

i 1 2 3
6 6 8
i 0 1 2 3 4 5 6 7 8 9 10
C[i] 0 1 5 8
rec 0 1 2 3 4 5 6 7 8 9 10
1 2 3
  1. 钢条长度为4:

​ 有四种情况:

  1. 剩下哪几种情况不在一一列举

算法实现

'''
钢条切割问题
这个算法主要需要实现以下这几种情况:
    1.C数组(记录权值)
    2.Rec数组(追踪效果)
    3.i数组(记录C[i]的各种情况的权重)
'''
def steel_bar_cutting(price_list, C, Rec):

    # 初始化i数组
    I = []

    # 遍历钢条长度 从1-len(price_list)
    for length in range(1, len(price_list)):
        
        # 初始化最大值, 最大值下标
        max_data = 0
        max_index = 0

        # 寻找切割钢条的 几种情况, 并寻找最大的值,和最大值的下标
        for m in range(1, length+1):
            m_data = price_list[m] + C[length-m]
            I.append(m)

            if m_data > max_data:
                max_data = m_data
                max_index = m
        # 把上述几种方案中最大值 赋值给C数组对应的位置, 把切割位置赋值给对应的Rec位置
        C[length] = max_data
        Rec[length] = max_index

# 追踪最优方案
def track(C, Rec):
    length = len(C) - 1
    i = length
    print(f"最大获利为:{C[i]}")

    print("获利方案为:")
    while(length > 0):
        print(f"在{Rec[i]}位置切一刀")
        i = length - Rec[i]
        length = i


#  初始化数据
price_list = [0,1,5,8,9,10,17,17,20,24,24]
C = [0 for i in range(len(price_list))]
Rec = [0 for i in range(len(price_list))]

steel_bar_cutting(price_list, C, Rec)
track(C, Rec)

标签:10,钢条,list,问题,length,Rec,切割
来源: https://www.cnblogs.com/zjhnuil/p/16256450.html