c++实现钢条切割问题

今天看了算法导论里面的动态规划(DP),有个有意思的问题:钢条切割来获取最大的收益。

书中讲到了几种求解方法,包括递归求解法、备忘录DP解法、自底向上的解法以及对解的重构。
书中给出不同解法的伪码,刚好需要练习c++,就有c++来实现DP求解钢条切割问题。

【递归求解】

// 钢条切割问题
// 自顶向下 递归实现

#include <iostream>
#include <time.h>

using namespace std;
int cut_rod(int len, int price_arr[]);

int main(int argc, char *argv[])
{
    clock_t start, finish;
    double duration;

    start = clock();
    int rod_len = 10;
    int p_arr[] = {0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30};

    int profit = cut_rod(rod_len, p_arr);
    cout << "profit = " << profit << endl;

    finish = clock();
    duration = (double)(finish - start)/CLOCKS_PER_SEC;  // 单位 s
    cout << "time cost = " << duration * 1000 << "ms" << endl;

    return 0;
}

/* 递归调用 cut_rod 函数
 * input: 钢条长度len, 单位钢条长度价格表price_arr[]
 * output: 长度为len的钢条的最佳收益
 *
 * 思想:
 * 1. 如果len==0,返回收益0
 * 2. 否则,把钢条切割为左边长度为i 和右边长度为len-i 的两段,
 *    长度为i的一段不在切割,收益为price_arr[i], 右边部分继续分解。
 * 注意:
 * 1. 程序存在访问风险;当输入长度大于 p_arr[]长度时,会访问到数组之外的元素;
 *    因此程序仅对 len < sizeof(p_arr)/sizeof(int) 的数据有效;
*/
int cut_rod(int len, int price_arr[])
{
    if (len == 0)
        return 0;

    int best_profit = -100;
    for (int i = 1; i <= len; i++)
    {
        best_profit = max(best_profit, price_arr[i] + cut_rod(len-i, price_arr));
    }
    return best_profit;
}

【自底向上DP重构解】

自底向上重构解包括自底向上求解法,因此在这儿只传重构的解法;

文章假定在钢条长度大于10英寸时,售价仍然为30美元,这样对输入的钢条长度就没有限制<当然这很不科学>;

/* DP 解决 钢条切割问题
 * 不仅返回长度为len的钢条的最大收益r[],而且返回切割情况s[](重构的解)
 * 重构的解也是分析子问题的性质决定的

*/

#include <iostream>
#include <string.h>

#define rod_len 17
#define LEN rod_len + 1

using namespace std;
void extend_bottom_up_cut_rod(int len, int price_arr[], int (&r)[LEN], int (&s)[LEN]);
void print_cut_rod_solution(int len, int price_arr[], int (&r)[LEN], int (&s)[LEN]);

int main(int argc, char *argv[])
{
    int price[] = {0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30};
    int r[LEN], s[LEN];
    memset(r, 0, sizeof(r));
    memset(s, 0, sizeof(s));

    print_cut_rod_solution(rod_len, price, r, s);

    return 0;
}

void extend_bottom_up_cut_rod(int len, int price_arr[], int (&r)[LEN], int (&s)[LEN])
{
    if (len == 0)
        return;

    for (int j = 1; j <= len; j++)
    {
        int p = -1000;
        for (int i = 1; i <= j; i++)  // 长度为j的钢条,切割i
        {
            int left_price;
            if (i > 10)
                left_price = price_arr[10];
            else
                left_price = price_arr[i];

            if (p < left_price + r[j-i])
            {
                p = left_price + r[j-i];
                s[j] = i;
            }
        }
        r[j] = p;
    }
}

void print_cut_rod_solution(int len, int price_arr[], int (&r)[LEN], int (&s)[LEN])
{
    extend_bottom_up_cut_rod(len, price_arr, r, s);
    cout << len << " inch rod price is " << r[len] << endl;

    cout << "the cut order is ";
    while (len > 0)
    {
        cout << s[len] << "  ";
        len -= s[len];
    }
}

  

时间: 2024-12-20 13:02:50

c++实现钢条切割问题的相关文章

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

动态规划算法概述 动态规划(dynamic programming)1是一种与分治方法很像的方法,都是通过组合子问题的解来求解原问题.不同之处在于,动态规划用于子问题重叠的情况,比如我们学过的斐波那契数列.在斐波那契数列的求解问题中,我们经常要对一个公共子问题进行多次求解,而动态规划算法,则对每个子问题只求解一次,将其解保存在一个表格中,从而避免了大量的冗余计算量. 动态规划算法常用于寻找最优解问题(optimization problem).而其规划大概可分为四步: 1.刻画一个最优解的结构特

算法导论--动态规划(钢条切割)

钢条切割问题 现有一段长度为n英寸的钢条和一个价格表pi,求切割方案使销售利益最大rn最大 长度为n英寸的钢条共有2n?1种不同的切割方案,因为可以每个整英寸的位置都可以决定切割或者不切割. 为了得到rn最大,可以把这个问题分成子问题求解,先切一刀,再考虑余下的部分的最大收益即求 rn=max{pk+rn?k}(k=1,2,3-n-1), pk部分不进行继续切割,直接作为一个整体售出 ; rn?k部分继续切割,考虑所有的情况,分成子问题. 求出所有k值对应的收益最大者作为rn 也有可能不进行任何

算法导论-动态规划-钢条切割

动态规划通常用于解决最优化问题,在这类问题中,通过做出一组选择来达到最优解.在做出每个选择的同时,通常会生成与原问题形式相同的子问题.当多于一个选择子集都生成相同的子问题时,动态规划技术通常就会很有效,其关键技术就是对每个这样的子问题都保存其解,当其重复出现时即可避免重复求解. 钢条切割问题 Serling公司购买长钢条,将其切割为短钢条出售.切割工序本身没有成本支出.公司管理层希望知道最佳的切割方案.假定我们知道Serling公司出售一段长为i英寸的钢条的价格为pi(i=1,2,…,单位为美元

算法导论读书笔记之钢条切割问题

算法导论读书笔记之钢条切割问题 巧若拙(欢迎转载,但请注明出处:http://blog.csdn.net/qiaoruozhuo) 给定一段长度为n英寸的钢条和一个价格表 pi (i=1,2, -,n),求切割钢条的方案,使得销售收益rn最大.注意,如果长度为n英寸的钢条价格pn足够大,最优解可能就是完全不需要切割. 若钢条的长度为i,则钢条的价格为Pi,如何对给定长度的钢条进行切割能得到最大收益? 长度i   1   2    3   4     5      6     7     8  

动态规划 钢条切割问题

#include <stdio.h> /* *钢条切割问题: *问题描述 假设公司出售一段长度为i英寸的钢条的价格为Pi(i = 1, 2, ...单位:美元),下面给出了价格表样例: 长度i 1 2 3 4 5 6 7 8 9 10 价格Pi 1 5 8 9 10 17 17 20 24 30 切割钢条的问题是这样的:给定一段长度为n英寸的钢条和一个价格表Pi,求切割方案,使得销售收益Rn最大. */ //假定价格一开始已经给出了,用全局的写死 #define max(x,y) (x)>

动态规划 -- 钢条切割

/* 动态规划和分治法相似,都是通过组合子问题的解来求解原问题. 但分治法是将 问题划分为互不相交的子问题,递归地求解子问题,再将它们的解组合起来,求出 原问题的解.与之相反,动态规划应用于子问题重叠的情况,即不同的子问题具有公共的 子问题.在这种情况下,分治法会做很多不必要的工作. 动态规划方法通常用来求解最优化问题,这类问题通常有很多可行解.我们希望寻找 具有最优值的解. 我们通常按照如下4个步骤来设计一个动态规划算法: · 刻画一个最优解的结构特征 · 递归地定义最优解的值 · 计算最优解

钢条切割问题求解方法及相关思考

钢条切割问题求解方法及相关思考 题目来源于<算法导论>第15章第一节.问题如下: 给定一个长度为n英寸的钢条和一个价格表pi(i=1,2,3,...n),求能够使销售收益rn最大的切割方案. 问题1:一共有多少种切割方式? 思路一:对于一个长度为n英寸的钢条,其中一共有n-1个节点可供切割,在每一个节点处都可以选择切割或者不切割,将对一根钢条的切割过程视为从第一个节点直到第n-1个节点逐一选择切割或者不切割的一个过程,利用乘法原理,可以算出来总共有2n-1种切割方案.以四个节点的钢条为例: 思

1、钢条切割问题

钢条切割问题的两种解法 #ifndef IRON_CUT_PRB_H #define IRON_CUT_RPB_H #include <iostream> int ironCutPrb(int *ironPrice,int Length); //这个是基于递规逄法的 int ironCutPrb_optimize(int *ironPrice,int Length); //这个是基于双层循环的. #endif #include"ironCutPrb.h" #define M

算法导论---------动态规划之钢条切割

动态规划方法通常用来求解最优化问题.动态规划算法设计步骤: 1.刻画一个最优解的结构特征. 2.递归定义最优解的值. 3.计算最优解的值,通常采用自底向上的方法. 4.利用计算出的信息构造一个最优解. 动态规划的实现方法: 带备忘的自顶向下法:此方法仍按自然的递归形式编写过程,但过程会保存每个子问题的解(通常保存在一个数组或散列表中).当需要一个子问题的解时,过程首先检查是否已经保存过此解.如果是,则直接返回保存的值,从而节省了计算时间:否则,按通常方式计算这个子问题. 自底向上法:这种方法一般