动态规划算法的一个特点就是通过记忆(memomorization), 记录下原问题的子问题的最优解(因为原始问题具有最优子结构), 从而 来避免通过递归, 重复的计算子问题。

下面, 我们首先假设我们关于不同长度的木头的价格表, 如下:

然后, 我们的目的就是通过选择切割方案使得我们的收益达到最大。

首先我们看看如何采用递归的方式解决这个问题。 一个recursive functio完全可以通过数学式子表示。

然后, 我们将我们的recursive version 通过引入memorization 来避免recursive, 即是我们的动态规划算法(dynamic programming)。递归程序如下:

#include <iostream>
#include <vector>
using namespace std;
double recurRodCutting(const vector<double>&p, int n) {
if (n < 1) return 0.0;
double Max = p[n]; //if donot cut off
for (int i = 1; i < n; i++) {
double temp = p[i] + recurRodCutting(p, n - i);
if (temp > Max) Max = temp;
}
return Max;
}
int main()
{
vector<double> prices = {1, 3, 3, 5, 5, 7, 8, 3, 10, 10};
cout << recurRodCutting(prices, 10) << endl;
return 0;
}

运行结果如下, 有问题的:

显然是有问题的,太大了, 那么问题出在哪里呢???

需要调试, 我们可以通过在程序中埋进去一些cout<< 以在输出查看结果, 或者我们也可以直接通过设置断点debug。

最终, 我们发现错误忘记了将第一个假如0 放在vector 的第一个元素了。 因为vector 的indice 是从0 开始的:

#include <iostream>
#include <vector>
using namespace std;
double recurRodCutting(const vector<double>&p, int n) {
if (n < 1) return 0.0; // base case
//    cout << n << endl;
double Max = p[n]; //if do not cut off
for (int i = 1; i < n; i++) {
double temp = p[i] + recurRodCutting(p, n - i);
//        cout << i << " " << temp << endl;
if (temp > Max) Max = temp;
}
return Max;
}
int main()
{
vector<double> prices = {0, 1, 3, 3, 5, 5, 7, 8, 3, 10, 10};
cout << recurRodCutting(prices, 10) << endl;
return 0;
}

运行的结果如下, 这是正确的:

上述的算法是brute force的形式, 时间复杂度达到指数级了。 很不实用。 下面我们使用dynamic programming 修改算法, 使得算法的时间复杂度降为O(n^2), 如下:

#include <iostream>
#include <vector>
using namespace std;
double recurRodCutting(const vector<double>&p, int n) {
if (n < 1) return 0.0; //base case
//    cout << n << endl;
double Max = p[n]; //if do not cut off
for (int i = 1; i < n; i++) {
double temp = p[i] + recurRodCutting(p, n - i);
//        cout << i << " " << temp << endl;
if (temp > Max) Max = temp;
}
return Max;
}
double dpRodCutting(const vector<double>&p2, int n) {
vector<double> r(n+1);
r[0] = 0.0;
for (int j = 1; j <= n; j++) {
double Max = p2[j];
for (int i = 1; i < j; i++) {
double temp = p2[i] + r[j - i];
if (temp > Max) Max = temp;
}
r[j] = Max;
}
//    for (auto x:r) cout << x << " ";
//    cout << endl;
return r[n];
}
int main()
{
vector<double> prices = {0, 1, 3, 3, 5, 5, 7, 8, 3, 10, 10};
cout << dpRodCutting(prices, 10) << endl;
return 0;
}

运行结果如下:

Rod cutting problem DP相关推荐

  1. 动态规划法(五)钢条切割问题(rod cutting problem)

      继续讲故事~~   我们的主人公现在已经告别了生于斯,长于斯的故乡,来到了全国最大的城市S市.这座S市,位于国家的东南部,是全国的经济中心,工商业极为发达,是这个国家的人民所向往的城市.这个到处都 ...

  2. 切割钢条问题(rod cutting problem)

    问题描述 Seriling公司购买长钢条,将其切割为短钢条出售.切割工序本身没有成本支出.公司管理层希望知道最佳的切割方案. 假定我们知道Serling公司出售一段长为ii ii英寸的钢条的价格为pi ...

  3. 算法题:Rod Cutting

    算法题:Rod Cutting 一.题目 二.代码 三.结果 一.题目 二.代码 lengths = [1,1,3,4] lengths = [5,4,4,2,2,8]def rodOffcut(le ...

  4. uva 10401 Injured Queen Problem(dp)

    题目链接:10401 - Injured Queen Problem 题目大意:给出一个字符串,要求在n * n(n为字符串的长度)的棋盘上摆放n个受伤的皇后,受伤的皇后只能攻击到同一列和它周围8个格 ...

  5. bestcoder #56 div 2 B Clarke and problem(dp)

    Clarke and problem  Accepts: 169  Submissions: 372  Time Limit: 2000/1000 MS (Java/Others)  Memory L ...

  6. acdream 1222 Quantization Problem [dp]

    称号:acdream 1222 Quantization Problem 题意:给出一个序列 a ,然后给出一个 n * m 的矩阵,让你从这个矩阵中选出一个序列k,使得sum(abs(ki - ai ...

  7. poj 3590 The shuffle Problem——DP+置换

    题目:http://poj.org/problem?id=3590 bzoj 1025 的弱化版.大概一样的 dp . 输出方案的时候小的环靠前.不用担心 dp 时用 > 还是 >= 来转 ...

  8. Codeforces 513G1 or 513G2 Inversions problem DP

    题目大意: 就是现在初始给定一个n个数的排列, 每次随机地选取任意的一个段的数进行反转, 问k次随机翻转之后逆序对的数量的期望 G1难度题目链接:http://codeforces.com/conte ...

  9. [CF1153F]Serval and Bonus Problem(dp/积分+OGF)

    其实这道题已经在我的学习笔记里面口胡过了- 但由于某种特殊原因-我写了一篇博客. 题面 Getting closer and closer to a mathematician, Serval bec ...

最新文章

  1. 在 DW 中插入 Flash 的参数详解
  2. 配置Keil C51配置开发 STC51单片机过程
  3. 成功解决You are using pip version 9.0.3, however version 10.0.1 is available. You should consider upgr
  4. Asp.Net Web API 2第七课——Web API异常处理
  5. java 招聘需求_Java人员要具备哪些技能 招聘需求包括什么
  6. 【DotNetMLLearn】.NET Core人工智能系列-概述
  7. android:background大小,小Demo小知识-android:foreground与android:background
  8. c#之task与thread区别及其使用
  9. python网络爬虫系列(0)——爬虫概述 http协议复习
  10. 软件工程讲义 9 创新的出路 走进作坊
  11. 《高性能mysql》之MySQL高级特性(第七章)
  12. (HDRP)全局光照技术初探(一)-光照模式与阴影技术
  13. three.js加载OBJ格式模型(vue中使用three.js51)
  14. PHP腾讯云短信接口
  15. php获得视频文件扩展名,php 获取文件扩展名的 n 种方法
  16. LMIC一直busy解决方法
  17. 赋值,浅拷贝,深拷贝区别和实现方法
  18. 如何修复DNS劫持?dns被劫持了怎么办有什么解决方法
  19. 课时31 永久储存:腌制一缸美味的泡菜
  20. 树莓派呼吸灯python代码

热门文章

  1. 【软件设计原则】CUPID——快乐的编码
  2. mysql readtimeout_MySQL Timeout解析
  3. 弘辽科技:拼多多不交保证金商品有曝光量吗?怎么提升曝光?
  4. 链路聚合以及生成树(STP)
  5. http://www.le.com/ptv/vplay/23225570.html#vid=23225570
  6. thinkphp3.23开发的“二当家的”通用CMS系统
  7. 应用概率统计-第七章 数理统计的基本概念
  8. 2015年中国移动云计算平台市场发展趋势分析
  9. 全球与中国增强现实远程协助软件市场现状及未来发展趋势
  10. Multi-Port Switch模块用法