動態規劃和分治策略相似,不同的是,它針對的問題所分解出的小問題數量很多且很多是重複的。動態規劃就是使得這些重複的小問題只需要計算一次,避免重複計算。
鋼條切割問題:給定一段長度為n英吋的鋼條和乙個**表pi(i=1,2,...,n)求切割鋼條方案,使得銷售收益rn最大。
注意,如果長度為n英吋的鋼條的**pn足夠大,最優解可能就是完全不需要切割(具體問題描述見演算法導論第三版第15章),以下都是用c語言實現,偽**參考演算法導論。
#include #include "limits.h"
#define int_min (-int_max - 1)
int cutrod(int *p,int n);
void main()
; printf("%d\n",cutrod(p,10));
}int cutrod(int *p,int n)
return (q);
}
上面只用了分治策略,這個演算法的效能是很差的,為t(n)=2^n,這種樸素遞迴演算法效率之所如此底是因為在子問題的求解中很多都是重複的
。動態規劃方法是仔細安排求解順序,對每個子問題只求解一次,並將結果儲存下來(其實是付出額外的記憶體空間來節省執行時間,是典型的時空權衡)。
動態規劃的兩種方法——帶備忘錄的自頂向下法和自底向上法,首先介紹下帶備忘錄的自頂向下法:
備忘錄方法是動態規劃方法的變形。與自底向上的動態規劃演算法不同的是,備忘錄方法的遞迴方式是自頂向下的,此方法仍然按照遞迴的形式,但過程中會儲存每個子問題的解。當需要乙個子問題的解時,首先檢查是否已經儲存過此解。如果是,則直接返回儲存的解,從而節省時間。
c實現:
#include #include "limits.h"
#define int_min (-int_max - 1)
int memorize_cut_rod_aux(int *p,int n,int *r);
int memorize_cut_rod(int *p,int n);
void main()
; printf("%d\n",memorize_cut_rod(p,10));
}int memorize_cut_rod_aux(int *p,int n,int *r)
*(r+n-1)=q;
return (q);
}int memorize_cut_rod(int *p,int n)
; int r[11]=;
for (int j=1;j<11;j++)
r[j]=q;
} for(int i=1;i<11;i++)
printf("%d\n",r[i]);
}
下面是上面的擴充套件版本,還儲存了最優解對應的第一段鋼條的切割長度sj;
#include #include #include "limits.h"
#define int_min (-int_max - 1)
void extended_bottom_up_cut_rod(int *p,int n,int *r);
void main()
; int r[11]=;
int s[11]=;
int n=10,q=int_min;
for (int j=1;j<=n;j++)
{ for (int i=1;i<=j;i++)
{ if (q
動態規劃 鋼條切割《演算法導論》
給定各長度鋼鐵單位 以及乙個長度為n的鋼條,求最大效益 1 10 分別為p include includeint memorized cut rod aux int p,int len,int r 樸素遞迴演算法 演算法複雜度為2 n級這裡寫 int cut rod int p,int len in...
演算法導論 動態規劃 鋼條切割
這幾天一直在看動態規劃的問題,看了看也沒想象中那麼難,但需要好好的分析一下問題,我們就拿演算法導論的鋼條切割問題好好理解一下,鋼條切割問題就是給你一段鋼條,讓你把鋼條切割成好多份,因為每一段鋼條都有不同的價值,我們要找到最優的切割方案,使切割成的鋼條價值最大。這道題我們可以用dfs直接搜尋,對每個狀...
動態規劃之鋼條切割
最近學習動態規劃,做個匯報吧!不同長度的鋼條,賣出時收益不同 1,1 2,5 3,8 4,9 5,10 6,17 7,17 8,20 9,24 10,30 問題就是我有一根鋼條,怎樣可以收益最大?這裡只寫思想,不寫過程,專注於演算法 一根鋼條,假如10公尺,我可以整體去賣,也可以切斷幾段去賣,那就用...