钢条切割问题

其实这个问题与我们大家熟知的背包问题本质上是一样的,我们来看一下问题本身:首先这里有一个价格表(表格摘自《算法导论》),表中列出了不同长度的钢条的价格:

长度 1 2 3 4 5 6 7 8 9 10
价格 1 5 8 9 10 17 17 20 24 30

假如现在我们有一块长度为5的钢条,那么我们通过切割这块钢条为不同大小的钢条后可以获得的最大利益是多少。
我们可以先从一块长度为5的钢条上截一块长度为a_legth(初始值为1)的钢条,然后考虑如何切割剩下长度为5-length的钢条,使得我们的利益最大。最终我们将a_length取不同值时所对应的最大利益进行比较,选出最大值就是我们能从一块长度为5的钢条上可以获取到的最大利益。那么我们又如何切割长度为5-length的钢条呢?这里我们可以依照之前的方式进行递推,直到最后的钢条长度变为0;

代码实现

SteelBar.h:
#pragma once
#include<iostream>
using namespace std;class SteelBar
{
public://价格int price[10+1];//钢条的长度int steel_length;//可获取的最大利益int interest;//创建指定长度的钢条void creat_steel();//切割钢条的最优方案int cut_steel(int n);
};SteelBar.cpp:
#include"SteelBar.h"int SteelBar::cut_steel(int n){if (n == 0){return 0;}//最大利益初始值为整段钢条的价格(未切割)int max_interest = price[n];//从左边切割下长度为i的一段for (int i = 1; i <= n; i++){//更新最大利益if (max_interest <= price[i]+cut_steel(n-i)){max_interest = price[i]+cut_steel(n-i);}}//返回最大利益return max_interest;
}void SteelBar::creat_steel(){cout<<"请输入要创建钢条的长度"<<endl;cin>>steel_length;//价格数组int price_array[10+1]={0,1,5,8,9,10,17,17,20,24,30};for (int i = 0; i < 11; i++){price[i] = price_array[i];}
}

分析与改进

通过运行上面的代码,我们发现两个问题:

  1. 随着切割钢条的长度的增加,程序的运行时间会变得特别的长。那能不能进行相关的改进呢?我们发现程序运行时间特别长的原因在于函数cut_steel反复使用相同的参数进行递归调用。那么我们这里其实是可以将函数cut_steel每次递归调用的结果进行记录,然后在每次递归之前从记录中查找相同参数的结果是否已经存在,假如存在则直接使用已有的结果,从而减少运行时间,假如不存在则进行递归调用,然后将结果记录下来。
  2. 程序每次只能输出切割对应长度钢条所能获取到的最大利益,但是无法获取与之对应的切割方案,我们可以在每次递归调用函数cut_steel来求出不同长度n所对应的最大利益的同时将与之对应的钢条的第一段的长度记录到一个数组中,最后通过该数组中便可以求出不同长度的钢条在获取到最大利益的时候与之对应的切割方案。

改进后的代码实现

SteelBar.h:
#pragma once
#include<iostream>
using namespace std;class SteelBar
{
public://价格int price[10+1]; //钢条长度int steel_length;  //不同长度的最优方案中第一段的长度int first_length[10+1];//不同长度所对应的最大利益int interest[10+1]; //创建指定长度的钢条void creat_steel();//切割钢条获取最大利益int cut_steel(int n);//输出最优方案void print_solution();
};SteelBar.cpp:
#include"SteelBar.h"int SteelBar::cut_steel(int n){if (n == 0){interest[0] = 0;return 0;}//查询是否有记录if (interest[n] != -1){return interest[n];}//最大利益初始值为整段钢条的价格(未切割)int max_interest = price[n];//从左边切割下长度为i的一段for (int i = 1; i <= n; i++){//更新最大利益if (max_interest <= price[i]+cut_steel(n-i)){max_interest = price[i]+cut_steel(n-i);//修改最大利益所对应的第一段的长度first_length[n] = i;}}//记录与n所对应的最大利益interest[n] = max_interest;//返回最大利益return max_interest;
}void SteelBar::creat_steel(){cout<<"请输入要创建钢条的长度"<<endl;cin>>steel_length;//价格数组int price_array[10+1]={0,1,5,8,9,10,17,17,20,24,30};for (int i = 0; i < 11; i++){price[i] = price_array[i];}//将不同长度所对应的最大利益进行初始化for (int i = 0; i <= steel_length; i++){//初始值为 -1interest[i] = -1;}//将不同长度的最优方案中的第一段的长度进行初始化for (int i = 0; i <= steel_length; i++){//初始值为 自身长度first_length[i] = i;}
}void SteelBar::print_solution(){cout<<"切割方案为:"<<endl;int j = 1;for (int i = steel_length; i > 0; ){if(i == first_length[i]){cout<<"第"<<j<<"段:"<<first_length[i]<<endl;break;}else{cout<<"第"<<j++<<"段:"<<first_length[i]<<endl;i = steel_length - first_length[i];}}
}

测试

#include"SteelBar.h"int main(){SteelBar steel_1;steel_1.creat_steel();steel_1.cut_steel(steel_1.steel_length);cout<<"最大利益为"<<steel_1.interest[steel_1.steel_length] <<endl;//输出切割方案steel_1.print_solution();
}

测试结果

钢条切割问题(自顶向下)相关推荐

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

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

  2. 动态规划,java实现算法导论15章钢条切割

    来自浙江理工大学在读研究生Yuner: github地址 个人博客地址 此问题dp式 :rn = max(pi + r(n-1)) 不使用dp,用普通的递归方式来求解 //使用普通的方法来计算钢条切割 ...

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

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

  4. 动态规划 — 钢条切割问题

    动态规划: 什么是动态规划? 动态规划算法的基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息.在求解任一子问题时 ...

  5. 《算法导论》15章-动态规划 15.1 钢条切割(含有C++代码)

    一.引入 动态规划方法通常用来求解最优化问题(optimizationproblem).这类问题可以有很多可行解,每个解都有一个值,我们希望寻找具有最优值(最小值或最大值)的解.我们称这样的解为问 题 ...

  6. 算法导论——钢条切割问题(C语言)

    <算法导论>在对动态规划讲解时,第一个问题就是钢条切割的问题. 在书中,对这个问题提供了3种思路 利用普通的递归来解,时间复杂度为O(2^n) 对普通的递归进行优化,使其带有记忆功能,减少 ...

  7. 动态规划—钢条切割问题与01背包问题

    目录 1.钢条切割问题 第一种求最优解方案: 第二种求最优解方案: 第一种方法是 带备忘的自顶向下法 第二种方法是 自底向上法 2.01背包问题 1,穷举法(把所有情况列出来,比较得到 总价值最大的情 ...

  8. 算法设计与分析——动态规划(二):钢条切割

    分类目录:<算法设计与分析>总目录 相关文章: · 动态规划(一):基础知识 · 动态规划(二):钢条切割 · 动态规划(三):矩阵链乘法 · 动态规划(四):动态规划详解 · 动态规划( ...

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

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

最新文章

  1. 腾讯云存储产品矩阵全面升级,发布三维生态战略
  2. python怎么变成exe文件_如何在python中知道CPython可执行文件是否是调试版本?
  3. django 1.3下关于静态文件staticfiles的设置
  4. macos实现输入文件输入结束符
  5. 信息学奥赛一本通(1240:查找最接近的元素)
  6. php 递归遍历文件夹,php递归遍历目录 | 学步园
  7. Xcode6+Cocos2d-x真机调试 报错
  8. 己所不欲,勿施于人的意思,这句话出自哪里?
  9. CCAI 2017 | 日本理化学研究所杉山将:弱监督机器学习的研究进展
  10. db2 sqlcode
  11. 饥荒一直服务器没有响应,饥荒总是启动服务器进不去 | 手游网游页游攻略大全...
  12. 用户体验的要素pdf_用户运营思路(35份)
  13. 大话移动通信(第2版)!(文末赠书福利)
  14. Springboot 整合 kafka 实现消息的发布和订阅
  15. Redis-14Redis超时命令
  16. android ndk neon,Android NDK开发之 NEON使用介绍
  17. Particle System调整
  18. 如何一键删除计算机的更新,快速清除win7系统更新缓存文件的详细步骤
  19. mysql 中创建自增的序列(Sequence)
  20. 浪子换钱系统 更新版源码

热门文章

  1. pandas统计表格中politics列字符个数
  2. video读取服务器本地的视频文件,javascript-video.js无法读取本地视频
  3. python英文字符频率统计_Python中怎样统计英文文本中的字母频次?
  4. 网站的服务器什么意思,网站服务器站点是什么意思
  5. Mysql系列之 -配置详情
  6. 使用nvm管理node和npm
  7. Window通过cmd命令测试服务器带宽性能的方法(IP测试)
  8. 计算机网络是主要的功能在于,计算机网络最基本功能之一是()。
  9. 【3Dsmax】入门
  10. WAIC直击:商汤科技展示AI应用落地最新成果