動態規劃--鏈條切割問題

   鋼條切割問題:給定一段長度爲n英寸的鋼條和一個價格表pi(i=1,2,...,n)求切割鋼條方案,使得銷售收益rn最大。算法

    注意,若是長度爲n英寸的鋼條的價格pn足夠大,最優解可能就是徹底不須要切割。性能

       思路:先將鋼條切成兩條,有n-1種方案,每一種方案的最優解都等於兩個子鋼條的最優解。咱們從這n-1個僞最優解再挑出最優的解了優化

       如下是僞代碼:spa

1 CUT-ROD(p,n)3d

2 if n == 0code

3     return 0blog

4 q=負無窮io

5 for i = 1 to nclass

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("----------------------------------\n");
    printf("長度爲 %d 的切割方案爲\n",n);
    while(n > 0)
    {
        printf("%3d",s[n]);
        n = n - s[n];
    }
    printf("\n");
}
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\n",i,r[i]);
    }
    Print_CUT_ROD_SOLUTION(p,9,s);
    system("pause");
    return 0;
}
相關文章
相關標籤/搜索