有一根钢条,和他的长度价格表,真么样切割才能使得售出的钢条收益最大。

不考虑钢条的切割损耗。

输入n 表示钢条的长度

价格表p[i] 表示长度为i的钢条出售的价格

———————————————————————————————————————————

这个问题使用动态规划有两种解法,一种是自顶向下的递归求解方法,第二种是自底向上的迭代求解法

#include <bits/stdc++.h>
using namespace std;//长度为n, 价格表p[i]表示长度为i的钢管能买的钱数
//一共有n+1个元素,下标从1开始,p[0]在自顶向下的递归方法中p[0] = 0;
//朴素算法
int CUT_POP(int *p, int n)
{if(n == 0)return 0;int q = INT_MIN;for(int i=1;i<=n;i++)q = max(q,p[i] + CUT_POP(p,n-i));return q;
}
/*自顶向下的递归求解方法*/
//参数:价格表p数组, 剩余长度为n,辅助数组r,表示已经计算出的r_index长度的钢筋做多可以买多少钱
int MEMOIZED_CUT_ROD_AUX(int *p, int n, int *r)
{int q;if(r[n] >= 0)return r[n];if(n == 0)      //相当于基线q = 0;else{q = INT_MIN;//这里其实就是枚举不同的长度组合//注意:p[10]是第11个元素//(1,9) (2,8) (3,7) (4,6) (5,5) (4,6) (6,4) (7,3) (8,2) (9,1) (10,0)//能够看到,这样做有其正确性,i = 10 的时候,n - i = 0,正好递归到基线处for(int i = 1;i<=n;i++)q = max(q, p[i] + MEMOIZED_CUT_ROD_AUX(p,n - i  ,r));}r[n] = q;return q;
}
int MEMOIZED_CUT_ROD(int *p, int n)
{int *r = new int[n+1];for(int i=0;i<=n;i++){r[i] = INT_MIN;}return MEMOIZED_CUT_ROD_AUX(p,n,r);
}
/*自底向上的迭代求解方法*/
int BOTTOM_UP_CUT_ROD(int *p, int n)
{int *r = new int[n+1];r[0] = 0;//枚举出每段长度的最优解1~nfor(int j=1;j<=n;j++){int q = INT_MIN;//同样也是枚举最优解,这个枚举是上面枚举的进一步枚举for(int i=1;i<=j;i++){q = max(q, p[i] + r[j-i]); //对于这里的正确性//把子问题拆成更小的子问题,i = 1, j = i 开始/* (i,j-i),i + (j-i) = j 所以,这里其实就是对于上面枚举的进一步枚举* (1,0)* (1,1) (2,0)* (1,2) (2,1) (3,0)* (1,3) (2,2) (3,1) (4,0)* ...* (1,9) (2,8) ... (10,0)* */}r[j] = q;}return r[n];
}struct Data
{int r[20];int s[20];
};
/*自底向上迭代法的升级版,可看出解的情况*/
Data* EXTENDED_BOTTOM_UP_CUT_ROD(const int *p, int n)
{Data *_data = new Data;_data->r[0] = 0;for(int j=1;j<=n;j++){int q = INT_MIN;for(int i=1;i<=j;i++){if(q < p[i] + _data->r[j-i]){q = p[i] + _data->r[j-i];_data->s[j] = i;    //这个不能放到循环外的原因是因为表达式的右值是 i,不能一次确定}}_data->r[j] = q;    //q = max(q, p[i] + r[j - i])}return _data;           //返回二元组
}
int main() {int n;cin >> n;int p[20];for(int i=1;i<=n;i++){cin >> p[i];}int ans;int choose;//选择方法cin >> choose;if(choose == 1) ans = CUT_POP(p,n);else if(choose == 2) ans = MEMOIZED_CUT_ROD(p,n);else if(choose == 3) ans = BOTTOM_UP_CUT_ROD(p,n);else {Data *temp = EXTENDED_BOTTOM_UP_CUT_ROD(p,n);ans = temp->r[n];while(n > 0){cout << temp->s[n] <<" ";n -= temp->s[n];}cout << endl;delete temp;}cout << ans <<endl;return 0;
}

其实这种动态规划和归并排序有着异曲同工之妙,都是通过把为题分成更小的子问题进而求解整个问题

只不过自顶向下的求解方法是从大问题看向小问题,自底向上的求解方法是从小问题看向大问题

第一种方法就是朴素算法,暴力枚举,但是就像斐波那契数列一样,该方法重复求解了子问题,造成了时间的浪费

第二种方法是第一种方法的改进版本,称作带备忘的自定向下法。此方法仍按照递归的方式求解,但过程会保存每个子问题的解(通常保存在一个数组或者是散列表中)。当需要一个子问题的解是,过程首先检查是否已经保存过子解。如果是,则直接返回保存的值,从而节省了计算时间;否则,按照通常的方式求解

第三种称为自底向上法。这种方法一般需要恰当定义子问题的“规模”的概念,是的任何子问题的求解都只依赖于“更小的”子问题求解。因为我们可以将子问题按规模排序(一个抽象过程),按从小到大的顺序求解。当求解某个子问题时,他一来那些更小子问题都已经求解完毕,结果已经保存。每个子问题只需求解一次,当我们求解他(也是第一次遇到它)时,它的所有前提子问题都已经求解完成

第四种方法是第三种方法的重构解,在其基础上加上了另一个数组s,并在求解规模为j的子问题时将第一段钢条的最优切割长度i保存在s[j]中,在输出的时候,因为是自底向上,所以求出当前最优子解向前寻找即可,因为只是把当前钢条假想成切割成两段即可,因为更小的子问题已经求解。

最重要的还是理解自底向上和自顶向下这两种设计模式,融汇贯通其他问题,类似的,动态规划也融汇了分治的思想。

动态规划——钢条切割相关推荐

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

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

  2. 算法导论 动态规划钢条切割问题 C语言

    动态规划钢条切割问题 动态规划(dynamic programming)与分治法类似.分治策略将问题划分为互不相交的子问题,递归求解子问题,再将子问题进行组合,求解原问题.动态规划应用于子问题重叠的情 ...

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

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

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

    文章目录 一.钢条切割定义 二.具体步骤 1.思考 2.代码思考 3.动态规划求解 4.伪代码 三:总结: 一.钢条切割定义 图为价格表 给定一段长度是n的钢条和一个价格表,求切割方案使得收益达到最大 ...

  5. 动态规划-钢条切割(java)

    数据结构与算法系列源代码:https://github.com/ThinerZQ/AllAlgorithmInJava 本文源代码:https://github.com/ThinerZQ/AllAlg ...

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

    给定一段长度为n英寸的钢条和一个价格表p,求切割钢条方案(钢条的长度均为整英寸),使得销售收益最大. 我们可以计算出长度为n英寸的钢条共有2的(n-1)次方种不同的切割方案. 为解决规模为n的原问题, ...

  7. 动态规划-钢条切割问题

    int BottomUpCutRod(int p[],int n) { int *r=new int[n+1]; r[0]=0; for (int j=1;j<=n;j++) { int q=- ...

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

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

  9. 钢条分割 动态规划java_【动态规划】初识,钢条切割问题

    正文之前其实动态规划老早之前就看过, 但是可惜的是印象不深,到今天彻底忘得差不多了,这两天看<算法导论>终于让我啃下了二叉搜索树和红黑树两个家伙,虽然还未曾熟练于胸,但是基本能用了...现 ...

最新文章

  1. SAP MM MRP运行后触发的PR单据里没有Assign采购组织?
  2. 对于FAMNIST中的十种动物和水果进行识别测试
  3. CABasicAnimation fillMode和removedOnCompletion
  4. 【渝粤教育】广东开放大学 网络市场与预测 形成性考核 (23)
  5. 字符串比较strcmp
  6. 6.18张朝阳再次直播带货    现拌现吃凉拌槐花上演“回忆杀”
  7. Emmet快速编写HTML代码
  8. 大一上期c语言实验报告2,大一上期C语言实验报告1熟悉实验环境
  9. 云丁智能锁使用说明书_出门不再带钥匙 云丁D2F智能指纹锁新体验
  10. VS2005精简版(二)
  11. 2017计算机考研统考,2017年计算机考研408统考真题及答案.pdf
  12. android jni stl,Android NDK中C++ STL库动态和静态链接
  13. tensorflow.js基本使用 图标识别(八)
  14. 游戏程序员的2013年终总结
  15. 四年运维人员的一些唠叨
  16. zkSnarks:QAP上构造零知识证明
  17. 【特征】PSI的计算
  18. 智慧井盖安装注意事项
  19. 【电子签名】如何使用Adobe Acrobat Pro DC给PDF文件添加自己的电子签名、选项勾选和日期填写
  20. 如何学Python?--捕蛇者说

热门文章

  1. 支付网关潜藏黑客!32万多含CVV码的财务信息被盗
  2. Java调用有道翻译API包括APPID/密钥地址注册
  3. 中国云计算产业渐成熟 加速传统产业转型升级
  4. PHP微信公众号网页授权登录 扫码登录 获取用户基本信息
  5. 用C++实现魔方并输出步骤
  6. 与泽风格--爱的季节
  7. 天池大数据比赛-天体分类总结
  8. 借助云开发实现小程序朋友圈的发布与展示
  9. 把经纬度转换成十进制
  10. Can‘t connect to MySQL server on ‘localhost‘ (10061)