ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

钢条切割问题

2022-05-11 09:02:31  阅读:176  来源: 互联网

标签:10 钢条 list 问题 length Rec 切割



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

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

问题定义

输入:

  • 钢条的长度n
  • 价格表pl(1≤ l ≤n):表示长度为l的钢条价格

输出:

  • 求得一组切割方法,令收益最大化

问题观察

  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:

​ 有两种情况

  • 切割一刀:结果为p[1] + C[2-1] = 2
  • 不切割:结果为p[2] = 5

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

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:

​ 有三种情况:

  • 在1那切割一刀:C[3] = p[1] + C[3-1] = 1 + C[2] = 6
  • 在2那切割一刀:C[3] = p[2] + C[3-2] = 5 + 1 = 6
  • 不切割:C[3] = p[3] = 8

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

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:

​ 有四种情况:

  • 在一那切割一刀:C[4] = p[1] + C[3] = 1 + 8 = 9

  • 在二那切割一刀:C[4] = p[2] + C[2] = 5 + 5 = 10

  • 在三那切割一刀:C[4] = p[3] + C[1] = 8 + 1 = 9

  • 不切割:C[4] = p[4] = 9

    从上面选择最大的哪一种情况:在二那切割一刀

    i 1 2 3 4
    9 10 9 9
    i 0 1 2 3 4 5 6 7 8 9 10
    C[i] 0 1 5 8 10
    rec 0 1 2 3 4 5 6 7 8 9 10
    1 2 3 2
  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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有