动态规划问题之 钢条切割

博客探讨了动态规划与分治算法的区别,强调动态规划在避免重复计算上的优势,用于解决最优化问题。文章通过钢条切割问题为例,指出递归解法效率低下,并详细介绍了如何运用动态规划的自顶向下和自底向上方法进行优化。
摘要由CSDN通过智能技术生成

动态规划与分治算法异同:

分治算法将问题划分为互不相交的子问题,递归的求解子问题。分治算法会做出许多不必要的工作,会反复求解那些公共子问题。而动态规划对子问题只求解一次,将其存储在一个表格里面,无需每次都重新计算。

动态规划通常用来求解最优化问题,这个问题可能有许多可行解,每个解都有一个值,我们希望寻找具有最优值的解。我们称这样的解为问题的一个最优解,而不是最优解,因为可能有多个解达到最优值。

这里写图片描述

这里写图片描述

这里写图片描述

(1)根据书中思路,我们可以设计一套递归算法来求解,但此种解法效率会很低,原因是函数会反复递归调用自己,T(N)=2^N;

价格表在上图中:

这里写图片描述

#include<iostream>
using namespace std;

int CUT_ROD(int n[], int); //定义递归函数参数是价格数组和钢管长度
int main() 
{
    int p[11];
    cout << "请输入价格表:";
    for (int i = 1; i <= 10; i++)
    {
        cin >> p[i];
    }                              //输入价格表格
    int k; //输入钢管长度 k
    cout << "请输入钢管长度:";
    cin >> k;
    int m = CUT_ROD(p,k);       
    cout << m;
    system("pause");
}
int max(int a,int b)//定义max函数
{
    return a?b : a > b;
}
int CUT_ROD(int p[],int n)
{
    int q = -10000;
    if (n == 0)
        return 0;
    for (int i = 1; i <= n; i++)
    {
        q = max(q,p[i] + CUT_ROD(p, n - i));//左边切割为i,右边递归不停的进行切割取最大值。

    }

    return q;


}

(2)使用动态规划法求解,动态规划会仔细安排求解顺序,牺牲一部分空间换取时间上的大幅度节省。自顶向下方法:

这里写图片描述

#include<iostream>
using namespace std;

int CUT_ROD(int n[], int,int[]); //定义递归函数参数是价格数组和钢管长度
int main()
{
    int p[11];  //存储价格的数组从标1开始。
    int r[11];  //存储子问题的最优解
    for (int i = 0; i++; i < 11)
    {
        r[i] = -100000;  //初始化为负值
    }

    cout << "请输入价格表:";
    for (int i = 1; i <= 10; i++)
    {
        cin >> p[i];
    }                              //输入价格表格
    int k; //输入钢管长度 k
    cout << "请输入钢管长度:";
    cin >> k;
    int m = CUT_ROD(p, k,r);
    cout << m;
    system("pause");
}
int max(int a, int b)  //定义max函数
{
    return a ? b : a > b;  
}
int CUT_ROD(int p[], int n,int r[])  
{
    int q;
    if (r[n] >= 0)
        return r[n];
    if (n == 0)
        q = 0;
    else q = -1000;

    for (int i = 1; i <= n; i++)
    {
        q = max(q, p[i] + CUT_ROD(p, n - i,r)); //利用已知的最优解来求大范围的最优解。

    }
    r[n] = q;

    return q;


}

(3)使用自底向上方法

这里写图片描述

#include<iostream>
using namespace std;

int CUT_ROD(int n[], int); //定义递归函数参数是价格数组和钢管长度
int main()
{
    int p[11];  //存储价格的数组从标1开始。

    cout << "请输入价格表:";
    for (int i = 1; i <= 10; i++)
    {
        cin >> p[i];
    }                              //输入价格表格
    int k; //输入钢管长度 k
    cout << "请输入钢管长度:";
    cin >> k;
    int m = CUT_ROD(p, k );
    cout << m;
    system("pause");
}
int max(int a, int b)  //定义max函数
{
    return a ? b : a > b;
}
int CUT_ROD(int p[], int n)
{
    int q=-1000;
    int r[11] ;
    r[0] = 0;
    int j; 
    for ( j = 1; j <= n; j++)
    {
        q = -10000;
        for (int i = 1; i <=j; i++)
        {
            q = max(q, p[i] + r[j - i]); //利用已知的最优解来求大范围的最优解。
        } 


    }
    r[j] = q;

    return q;


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值