首页 > 代码库 > 动态规划之钢条切割

动态规划之钢条切割

动态规划方法通常用来求解最优化问题。动态规划算法设计步骤:

1.刻画一个最优解的结构特征。

2.递归定义最优解的值。

3.计算最优解的值,通常采用自底向上的方法。

4.利用计算出的信息构造一个最优解。

动态规划的实现方法:

带备忘的自顶向下法:此方法仍按自然的递归形式编写过程,但过程会保存每个子问题的解(通常保存在一个数组或散列表中)。当需要一个子问题的解时,过程首先检查是否已经保存过此解。如果是,则直接返回保存的值,从而节省了计算时间;否则,按通常方式计算这个子问题。

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

问题:公司购买长钢条,将其切割为短钢条出售。切割工序本身没有成本支出。公司管理层希望知道最佳的切割方案。

假定我们知道公司出售一段长度i英寸的钢条的价格为pi(i=1,2,...,单位为美元)。钢条的长度均为整英寸。图给出了一个价格表的样例。

自底向上的伪代码:

BOTTOM-UP-CUT-ROD(p,n)
1   let r[0..n]be a new array
2   r[0]=0
3   for j=1 to n
4      q=-1
5      for i=1 to j
6         q=max(q,p[i]+r[j-i])
7      r[j]=q
8   return r[n]
整个程序的实现为:

#include <iostream>
#include <vector>

using namespace std;

void print_s(vector<int> s, int n);
//钢条切割动态规划之自底向上
vector<int> Bottom_Up_Cut_Rod(vector<int> price, int n);
int main()
{
    int i = 0;
    int a[11] = {0,1,5,8,9,10,17,17,20,24,30};
    vector<int> price;
    while(i < 11)
    {
        price.push_back(a[i]);
        i++;
    }

    vector<int> s(Bottom_Up_Cut_Rod(price, 8));
    cout<<"The best cut :";
    print_s(s, 8);
    return 0;
}

vector<int> Bottom_Up_Cut_Rod(vector<int> price, int n)
{
    vector<int> result(n+1, -1);
    vector<int> s(n+1, -1);
    int i, j, q;
    result[0] = 0;
    s[0] = 0;

    for(i = 1; i < n+1; i++)
    {
        q = -1;
        for(j = 1; j < i+1; j++)
            if(q < price[j]+result[i-j])
            {
                q = price[j] + result[i-j];
                s[i] = j;
            }
        result[i] = q;
    }
    cout<<"The max profit :"<<result[n]<<endl;
    return s;
}

void print_s(vector<int> s, int n)
{
    while(n)
    {
        cout<<s[n]<<"\t";
        n = n - s[n];
    }
}