CLRS 15.1钢条切割

本文深入探讨了切割绳子问题的递归解法及优化,通过数学归纳法推导出T(n) = 2^n的公式。进一步介绍了两种动态规划方法:自底向上和备忘录法,详细展示了如何实现并解决该问题。最后,通过代码实现验证了解法的有效性。
摘要由CSDN通过智能技术生成

15.1-1
T(n)=1+j=0n1T(j)=1+T(0)+...+T(n1)
T(n1)=1+T(0)+...+T(n2)

由上面两式得 T(n)=2T(n1) ,通过数学归纳法可得 T(n)=2n

15.1-2
根据书中的数据,当长度为 4 的时候,每英寸的价值最高的是长度为 3 的时候,切割方案就是 3+1,得到的价值是 9。实际上不切割的价值也是 9,另外最好的切割方案是 2+2,此时的价值是 10 。

15.1-3
我们把自底向上的CUT-ROD修改一下,先将 q 设置为没有切割时的价值,然后将第二个 for 改成 for i = 1 to j - 1

MODIFIED-CUT-ROD(p, n, c)
    let r[0..n] be a new array
    r[0] = 0
    for j = 1 to n
        q = p[j] 
        for i = 1 to j - 1
            q = max(q, p[i] + r[j - i] + c)
        r[j] = q
    return r[n]

运行代码

#include <iostream>
#include <cstring>
using std::cout;
using std::endl;

//参数分别表示价格表,长度,固定成本,保存切割方案数组
int BOTTOM_UP_CUT_ROD(int *price,int n,int c,int *s)
{
    int *r = new int[n+1];
    *(r+0) = 0;
    for(int j = 1; j <= n; ++j)
    {
        int q = *(price + j - 1);
        *(s + j - 1) = j;
        for(int i = 1; i < j; ++i)
        {
            int temp = *(price + i - 1) + *(r + j - i) - c;
            if(q < temp)
            {
                q = temp;
                *(s + j - 1) = i;
            }
        }
        *(r + j) = q;
    }
    int ret = *(r + n);
    delete []r;
    return ret;
}

void PRINT_CUT_ROD_SOLUTION(int *s,int n)
{
    while(n > 0)
    {
        cout << s[n-1] << ' ';
        n -= s[n-1];
    }
}

int main()
{
    int p[] = {1,5,8,9,10,17,17,20,24,30};
    int s[10];
    memset(s,0,sizeof(int)*10);
    for(int i = 1; i < 11; ++i)
    {
        cout << "Length " << i << "'s price is: " << BOTTOM_UP_CUT_ROD(p,i,0,s) << endl;
        cout <<  "cut rod solution is: ";
        PRINT_CUT_ROD_SOLUTION(s,i);
        cout << endl;
    }
    return 0;
}

15.1-4
伪代码略,给出运行代码

#include <iostream>
#include <climits>
#include <cstring>
using std::cout;
using std::endl;

//参数分别表示价格表,长度,备忘机制数组r,保存切割方案数组
int MEMORIZED_CUT_ROD_AUX(int *price,int n,int *r,int *s)
{
    if(n == 0)
        return 0;
    if(*(r + n -1) >= 0)
        return *(r + n -1);

    int q = INT_MIN;
    for(int i = 0; i < n; ++i)
    {
        int temp = *(price + i) + MEMORIZED_CUT_ROD_AUX(price,n-i-1,r,s);
        if(q < temp)
        {
            q = temp;
            *(s + n - 1) = i + 1;
        }
    }
    *(r + n - 1) = q;
    return q;
}

int MEMORIZED_CUT_ROD(int *price,int n,int *s)
{
    int *r = new int[n];
    for(int i = 0; i < n; ++i)
        *(r + i) = INT_MIN;
    return MEMORIZED_CUT_ROD_AUX(price,n,r,s);
}

void PRINT_CUT_ROD_SOLUTION(int *s,int n)
{
    while(n > 0)
    {
        cout << s[n-1] << ' ';
        n -= s[n-1];
    }
}

int main()
{
    int p[] = {1,5,8,9,10,17,17,20,24,30};
    int s[10];
    memset(s,0,sizeof(int)*10);
    for(int i = 1; i < 11; ++i)
    {
        cout << "Length " << i << "'s price is: " << MEMORIZED_CUT_ROD(p,i,s) << endl;
        cout <<  "cut rod solution is: ";
        PRINT_CUT_ROD_SOLUTION(s,i);
        cout << endl;
    }
    return 0;
}

15.1-5
这个很简单,就直接写了,很显然是 O(n)

FIBONACCI(n)
    let fib[0..n] be a new array
    fib[0] = fib[1] = 1
    for i = 2 to n
        fib[i] = fib[i-1] + fib[i-2]
    return fib[n]

子问题图包括 n+1 个顶点 v0,v1,...,vn ,对 i=2,3,...,n ,顶点 vn 有两条边,分别指向顶点 vi1,vi2 。因此一共有 2n2 条边。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值