动态规划问题首先是分解原始问题为相同形式的子问题,是利用重复的子问题不再重新计算的算法。

钢锯切割是其中一个典型代表,子问题形式为左边不切割,右边的进行切割,首先是朴素的递归形式,时间复杂度是2的n次方,

代码1

#-*- coding: utf8 -*-
import time
'''钢条切割问题的自顶向下版本,直接进行递归p是长度对应的价格表n是现在的钢条长度求解最大利润'''
def CUT_ROD(p, n):if n is 0:return 0q = 0for i in xrange(1, n+1):q = max(q, p[i]+CUT_ROD(p, n-i))return qp = {0:0,1:1,2:5,3:8,4:9,5:10,6:17,7:17,8:20,9:24,10:30}
def main():n = 24max_key = max(p.keys())if n > max_key:for i in xrange(max_key+1, n+1):p[i] = 0        #原来的没有p[i],否则报keyerrorp[i] = CUT_ROD(p, i)print n, p[n]if __name__ == '__main__':begin = time.time()main()print 'total run time', time.time()-begin

用时:

>>>
24 70
total run time 35.2200000286

此方式效率看得出是很低的,有两种方式可以优化上面的方案:

加入备忘机制,就是中途将计算的子问题的最优解存储起来

代码2

#-*- coding: utf8 -*-
import time
''' “自顶向下”带备忘,是朴素递归带备忘的形式 top-down with memoization '''
def MEMOIZED_CUT_ROD(p, n):r = []      #用来存储长度为n的最大收益,就是所有子问题的解for i in xrange(0, n+1):    # 0 to n  初始化r.append(-1)return MEMOIZED_CUT_ROD_AUX(p, n, r)
def MEMOIZED_CUT_ROD_AUX(p, n, r):if r[n]>=0:return r[n]     #这里就是已经存在的长度为n的最大收益,如果存在则直接取出,不再计算if n is 0:q = 0else:q = -1for i in xrange(1, n+1):    # 1 to nq = max(q, p[i] + MEMOIZED_CUT_ROD_AUX(p, n-i, r))r[n]=qreturn qp = {0:0,1:1,2:5,3:8,4:9,5:10,6:17,7:17,8:20,9:24,10:30}
def main():n = 24max_key = max(p.keys())if n > max_key:for i in xrange(max_key+1, n+1):p[i] = 0        #原来的没有p[i],否则报keyerrorprint MEMOIZED_CUT_ROD(p, n)if __name__ == '__main__':begin = time.time()main()print 'total run time', time.time()-begin

用时:

>>>
70
total run time 0.0120000839233

看出优化是很有效的

第二种方式是自底向上的寻找最优解,更加简单而且执行速度更快:

代码3

#-*- coding: utf8 -*-
import time
''' 自底向上法 bottom-up method '''
def BOTTOM_UP_CUT_ROD(p, n):r = []          #用来存储长度为n的最大收益,就是所有子问题的最优解for i in xrange(0, n+1):    # 0 to n 初始化r.append(-1)r[0] = 0    #长度为0, 收益为0for j in xrange(1, n+1):q = -1for i in xrange(1, j+1):q = max(q, p[i]+r[j-i])r[j] = qreturn r[n]
p = {0:0,1:1,2:5,3:8,4:9,5:10,6:17,7:17,8:20,9:24,10:30}
def main():n = 24max_key = max(p.keys())if n > max_key:for i in xrange(max_key+1, n+1):p[i] = 0        #原来的没有p[i],否则报keyerrorprint BOTTOM_UP_CUT_ROD(p, n)if __name__ == '__main__':begin = time.time()main()print 'total run time', time.time()-begin

用时:

>>>
70
total run time 0.0110001564026

第二种方式更加简洁,且没有递归,因为一程序都有递归调用的最大深度的限制,两者渐进时间一致,但是因为少了递归,第二种方式的系数小一些

稍加修改上面的代码,使之不仅返回最大收益,而且打印出最优解

#-*- coding: utf8 -*-
import time
''' 输出最优解的自底向上法 bottom-up method '''
def EXTENDED_BOTTOM_UP_CUT_ROD(p, n):r, s = [], []   # r用来存储长度为n的最大收益,就是所有子问题的最优解# s存储对长度为n的钢条切割的最优解对应的第一段钢条的切割长度for i in xrange(0, n+1):    # 0 to n 初始化r.append(-1)s.append(0)r[0] = 0    #长度为0, 收益为0for j in xrange(1, n+1):q = -1for i in xrange(1, j+1):if q < p[i]+r[j-i]:q = p[i]+r[j-i]s[j] = ir[j] = qreturn r, s
def PRINT_CUT_ROD_SOLUTION(p, n):r, s = EXTENDED_BOTTOM_UP_CUT_ROD(p, n)print 'max revenue is', r[n]while n>0:print s[n]n = n-s[n]
p = {0:0, 1:1, 2:5, 3:8, 4:9, 5:10, 6:17, 7:17, 8:20, 9:24, 10:30}
def main():n = 9max_key = max(p.keys())if n > max_key:for i in xrange(max_key+1, n+1):p[i] = 0        #原来的没有p[i],否则报keyerrorPRINT_CUT_ROD_SOLUTION(p, n)if __name__ == '__main__':begin = time.time()main()print 'total run time', time.time()-begin

输出:

>>>
max revenue is 25
3
6
total run time 0.0220000743866

转载于:https://blog.51cto.com/herculeser/1340213

动态规划之钢锯切割问题相关推荐

  1. 算法导论15.1动态规划之钢条切割

    动态规划与钢条切割 1.分治算法与动态规划 相同点: 都是通过组合子问题的解来求解原问题 不同: 1.分治将问题划分为互不相交的子问题,递归地求解子问题,在将它们的解组合起来,求出原问题. 2.动态规 ...

  2. 算法导论-动态规划(钢条切割问题)

    写下文章来记录下自己学习算法导论的笔记 文章目录 写下文章来记录下自己学习算法导论的笔记 动态规划的目的 设计动态规划算法 钢条切割问题 问题描述 刻画问题结构(建立方程) 递归方程建立 带备忘录的自 ...

  3. 动态规划算法---钢条切割

    算法进阶---动态规划算法 钢条切割问题: 程序实现: 钢条切割问题: 程序实现: 方法一和方法二是对程序实现的不断深入,逐渐降低算法实现的时间复杂度. p = [0, 1, 5, 8, 9, 10, ...

  4. 《算法导论》中动态规划求解钢条切割问题

    动态规划算法概述 动态规划(dynamic programming)1是一种与分治方法很像的方法,都是通过组合子问题的解来求解原问题.不同之处在于,动态规划用于子问题重叠的情况,比如我们学过的斐波那契 ...

  5. 动态规划之钢筋切割问题

    目录 一 问题描述 二 原理 三 代码 四 输出结果 一 问题描述 注 : 资料来源于<算法导论>第15章动态规划. 二 原理 三 代码 自顶向下解法 /*** * 采用自顶向下解法* * ...

  6. 动态规划算法 - 钢条切割问题

    1 #include"stdafx.h" 2 #include<iostream> 3 using namespace std; 4 /* 5 动态规划算法: 6 1. ...

  7. 《算法导论》学习(十七)----动态规划之钢条切割(C语言)

    文章目录 前言 一.钢条切割问题 1.问题背景 2.问题描述 3.问题的难点 (1)情况较多 (2)消除重复子问题 二.问题解决方案 1.问题的特点 (1)最优化子结构 (2)重复子问题 2.最优化解 ...

  8. 动态规划:钢条切割问题

    一.题目 钢条切割问题 是<算法导论>一书中介绍动态规划时的一道引题.即: 某公司购买长钢条,将其切割为短钢条出售.假设切割工序没有成本支出,已知长度为 i 的钢条出售价格为 pi ,钢条 ...

  9. 数据结构(python) —— 【34: 动态规划之钢条切割问题】

    钢条切割问题 1. 问题 某公司出售钢条,出售价格与钢条长度之间的关系如下表: 问题:现有一段长度为n的钢条和上面的价格表,求切割钢条方案,使得总收益最大. 2. 思路 思考: 长度为n的钢条的不同切 ...

最新文章

  1. java for xp_20155328 《Java程序设计》实验三 敏捷开发与XP实践 实验报告
  2. 四大价值观和12准则
  3. 什么是四路串口服务器?
  4. 基于链路思想的SpringBoot单元测试快速写法
  5. java new对象 =null_在Java中将对象分配为null会影响垃圾回收吗?
  6. 做折线图_python的visvis库做折线图(line.py)代码详解
  7. [Angualr 2] Using FormBuilder
  8. C和指针---第八章:数组
  9. intelj idea中除了Find Usage外的另一种查找级联调用的方法
  10. 输入广义表建立子女兄弟链表示的树
  11. 易语言-数据类型及其长度
  12. 视频直播CDN系统架构简析
  13. jzoj 3457. 【NOIP2013模拟联考3】沙耶的玩偶(doll) (Standard IO)
  14. Python环境与PyCharm编辑器的安装教程
  15. 一篇五分生信临床模型预测文章代码复现——Figure1 差异表达基因及预后基因筛选——火山图,Venn图,热图绘制(二)
  16. 已解决-Mounty 挂载NTFS报错:卷“BOOTCAMP“不可重新挂载
  17. c语言中函数名可不可以由用户命名,C语言中变量名及函数名的命名规则与驼峰命名法...
  18. SQL性能优化以及性能测试
  19. 2048小游戏HTML网页版源码共享
  20. 手把手教QT—2. 启航篇,手动建工程及工程文件讲解

热门文章

  1. 11G Concept 第三章翻译 Indexes and Index-Organized Tables(索引和索引组织表)
  2. LG Optimus G Pro 相关
  3. 印度来了,印度要去了
  4. 高富帅+白富美 15名程序员界性感的奇葩
  5. php 文件上传至OSS及删除远程阿里云OSS文件
  6. 非平稳信号的自适应分解算法:EMD、SSA、ITD、VMD以及其变体之间的总结与对比
  7. python 抽取xml_python批量爬取xml文件
  8. windows无法验证此文件的数字签名 winload.exe 0xc0000428
  9. 西部数码 php.ini,php放在虚拟主机的哪个文件夹
  10. Linux下cronolog安装配置