• 动态规划--链条切割问题


       钢条切割问题:给定一段长度为n英寸的钢条和一个价格表pi(i=1,2,...,n)求切割钢条方案,使得销售收益rn最大。

        注意,如果长度为n英寸的钢条的价格pn足够大,最优解可能就是完全不需要切割。

           思路:先将钢条切成两条,有n-1种方案,每一种方案的最优解都等于两个子钢条的最优解。我们从这n-1个伪最优解再挑出最优的解了

           以下是伪代码:

    1 CUT-ROD(p,n)

    2 if n == 0

    3     return 0

    4 q=负无穷

    5 for i = 1 to n

    6     q=max(q,p[i]+CUT-ROD(p,n-i))

    7 return q

    上面只用了分治策略,这个算法的性能是很差的T(n)=2n,在子问题的求解中很多都是重复的。

    动态规划就是避免这些重复。一般有两个思路1.记录中间解 

     1 MEM-CUT-ROD

     2 let r[0..n] be a new array

     3 for i = 0 to n

     4     r[i]=负无穷

     5 return MEM-CUT-ROD-AUX(p,n,r)

     6

     7 MEM-CUT-ROD-AUX(p,n,r)

     8 if r[n]>=0

     9     return r[n]

    10 if n==0

    11     q=0

    12 else q=负无穷

    13     for i=1 to n

    14         q=max(q,p[i]+MEM-CUT-ROD-AUX(p,n-i,r))

    15 r[n]=q

    16 return q

     2.通过对问题求解顺序的合理安排,达到避免重复

    1 BOTTOM-UP-CUT-ROD(p,n)

    2 let r[0..n] be a new array

    3 r[0]=0

    4 for j=1 to n

    5     q=负无穷

    6     for i=1 to j

    7         q=max(q,p[i]+r[j-i])

    8     r[j]=q

    9 return r[n]

    下面的伪代码还保留了切割长度

     1 EXTEND-BOTTOM-UP-CUT-ROD(p,n)

     2 let r[0..n] and s[0..n] be new arrays

     3 r[0]=0

     4 for j = 1 to n

     5     q=负无穷

     6     for i =1 to j

     7         if q < p[i]+r[j-i]

     8             q=p[i]+r[j-i]

     9             s[j]=i

    10             r[j]=q

    11 return r and s

    12

    13 PRINT-CUT-ROD-SOLUTION(p,n)

    14 (r,s)=EXTEND-BOTTOM-UP-CUT-ROD(p,n)

    15 while n >0

    16     print s[n]

    17     n=n-s[n]

    使用动态规划方法求解的最优化问题应该具备两个要素:最优子结构和子问题重叠

    c语言实现代码;

    #define MinNum -200
    #define MaxNum 20
    #include<stdio.h>
    #include<stdlib.h>
    int Max(int a, int b)
    {
        return a > b ? a : b;
    }
    int CUT_ROD(int p[],int n)
    {
        int q;
        if(n == 0)
            return 0;
        q = MinNum;
        for(int i = 1 ; i <= n; i++)
        {
            q = Max(q,p[i] + CUT_ROD(p,n-i));
        }
        return q;
    }
    int Bottom_UP_ROD(int p[],int n , int r[])
    {
        int q;
        for(int i = 1; i <= n ; i++)
            r[i] = MinNum;
        r[0] = 0;
        for(int j = 1; j <= n ; j++)
        {
            q = MinNum;
            for(int i = 1 ; i <= j ;i++)
            {
                q = Max(q,p[i] + r[j-i]);
            }
            r[j] = q;
        }
        return r[n];
    }
    int MEMOIZED_CUT_ROD_AUX(int p[],int n , int r[])
    {
        int q;
        if(r[n] >= 0)
            return r[n];
        if(n == 0)
             q = 0;
        else
        {
            q = MinNum;
            for(int i = 1 ; i <= n ; i++)
                q = Max(q,p[i] + MEMOIZED_CUT_ROD_AUX(p,n-i,r));
        }
        r[n] = q;
        return q;
    }
    void MEMOIZED_CUT_ROD(int p[],int n)
    {
        int r[MaxNum];
        for(int i = 1 ; i <= n ; i++)
            r[i] = MinNum;
    }
    void EXTEND_DOWN_UP_ROD(int r[],int s[],int p[], int n)
    {
        r[0] = 0;
        for(int j = 1 ; j <= n ;j++)
        {
            int q  = MinNum;
            for(int i =1 ; i <= j ; i++)
            {
                if(q < p[i] + r[j-i])
                {
                    q = p[i] + r[j-i];
                    s[j] = i;
                }
            }
            r[j] = q;
        }
    }
    void Print_CUT_ROD_SOLUTION(int p[], int n , int s[])
    {
        printf("----------------------------------
    ");
        printf("长度为 %d 的切割方案为
    ",n);
        while(n > 0)
        {
            printf("%3d",s[n]);
            n = n - s[n];
        }
        printf("
    ");
    }
    int main()
    {
        int p[] = {0,1,5,8,9,10,17,17,20,24};
        int r[MaxNum];
        int s[MaxNum];
        EXTEND_DOWN_UP_ROD(r,s,p,9);
        for(int i = 1; i <= 9; i++)
        {
            printf("长度为%d的收益最大为:%d
    ",i,r[i]);
        }
        Print_CUT_ROD_SOLUTION(p,9,s);
        system("pause");
        return 0;
    }
  • 相关阅读:
    [原创] 如何在ietester下使用firebug
    Undeclared identifier: 'XXXX'
    图解SQL多表关联查询
    如何去掉Delphi自动生成的~.pas等临时文件
    DataSetProvider的Option属性
    DELPHI DATASNAP 2010 入门操作(2)不写一行代码,绿色三层我也行
    Windows下搭建Android开发环境
    Delphi快捷键大全
    DevExpress的TcxDBLookupComboBox使用方法及问题
    SQL的重复记录处理大全
  • 原文地址:https://www.cnblogs.com/joyclub/p/4874972.html
Copyright © 2020-2023  润新知