钢条切割问题

问题描述

给定一段长度为n英寸的钢条和一个价格表 pi (i = 1,2,……,n ) , 求切割钢条方案,使得收益 rn 最大。

分析问题

随便给定一个价格表

长度i12345678910
价格 pi 1589101717202430

得出以下结果

钢条长度n12345678910
收益 ri 15810131718222530
切割方案1232+22+361+6或2+2+32+63+610

可以看出该问题满足最优子结构性质:问题的最优解由相关子问题的最优解组合而成,而这些子问题可以独立求解。比如长度为7的钢条可以切割为长度为1及长度为6的两段钢条,很明显长度为6的钢条可以继续切割,也可以不切割,所以要求解出长度为7的钢条得到最多收益的切割方案首先得求解出长度为6的最佳切割方案,此时称长度为6的钢条切割问题为长度为7的钢条切割问题的子问题。
到这里可能有的人会想到用递归算法来解决问题,不过对这个问题递归算法恰恰是不可取的,当n稍微大一些,比如n=50,程序就要运行挺久时间了,因为程序作了很多无用功,及对同一个子问题多次求解,由上面的表格可以看出长度为7,8,9的钢条切割问题都依赖于长度为6的钢条切割问题,用递归算法将多次求解长度为6的钢条切割问题。
自然地我们应该想到将长度为6的钢条切割方案保存起来,而不是重复地进行求解。

这就是所谓的动态规划方法:付出额外的内存空间来节省计算时间,是典型的时空权衡的例子。

动态规划有两种等价的实现方法:带备忘的自顶向下法(如上所述,和递归类似,只是将结果保存下来,以免重复求解造成资源浪费)和自底向上法(将子问题按规模n排序,按由小至大的顺序进行求解)。

解决问题

下面给出自底向上的求解钢条切割问题的python实现。

#coding=utf-8
file=open("result.txt","w")

import random
n=20
data=[]
for i in range(n):
    data.append(random.randint(0,10000))



file.write("长度由1到"+str(len(data))+"的钢条的价格分别为:"+str(data)+"\n")

s=[0 for i in range(len(data)+1)]
def bottomUpCutRod(p):
    r=[-1 for i in range(len(p)+1)]
    r[0]=0
    for j in range(1,len(p)+1):
        for i in range(1,j+1):
            if r[j]<p[i-1]+r[j-i]:
                r[j]=p[i-1]+r[j-i]
                s[j]=i
    return r[len(p)]

file.write("最大收益为:"+str(bottomUpCutRod(data))+"\n")

length=[]
def detail(total,cut):
    if total==cut:
        return 0
    if detail(cut,s[cut])==0:
        length.append(cut)
    if detail(total-cut,s[total-cut])==0:
        length.append(total-cut)    
    return 1

if detail(len(data),s[len(data)])==0 :
    file.write("不切割")
else:
    file.write("切割出的钢条长度为分别:"+str(length))
file.close()

代码有问题的地方以及说错的地方还请指出,谢谢!

有任何不解的地方请留言,很乐意为您解答。


欢迎转载,但请附上原地址http://blog.csdn.net/jiaxingzheng/article/details/44230117,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值