前言:”與其每天擔心未來,不如努力現在。別對自己喪失信心,成長的路上,只有奮鬥才能給你最大的安全感“
你好,我是夢陽辰,讓我們一起加油,一起努力吧!
1. 動態規劃解決的問題
- 動態規劃解決遞歸算法大量的冗餘計算,遞歸算法時自頂向下思想,中間有太多重複計算,而動態規劃自底向上遞推求解,用表(通常爲數組)記錄子問題的解,以便保存和以後的檢索,從最簡單的問題的解填起,以自底向上的方式填表,這就保證了當我們求解一個子問題的時候,所有的與子問題相關子子問題,都可以從表中直接取用,不必重複計算。即用空間換取時間。但是,對於計算問題的解,還需利用遞歸公式。
- 動態規劃的由來:
由於20世紀40年代末期,還沒有出現計算機,這個動態填表的方法稱爲動態規劃。
2.動態規劃的算法思想
- 動態規劃的思想的歷史由來:
- 動態規劃的總體思想:
動態規劃算法與分治算法類似,其基本思想也是將待求解的問題分解成若干子問題,先求解子問題,再從子問題的解得到原問題的解。在用分治法求解時,有些子問題被重複計算了許多次。而動態規劃保存已解決的子問題的答案,而在需要時再找出以求得的答案,就可以避免大量的重複計算,從而得到多項式時間算法。 - 動態規劃用一個表來記錄所有已解決的子問題的答案,具體的動態規劃算法是多種多樣的,但它們具有相同的填表方式。
- 分治算法的特徵
- 如果不具備第三條特徵,則可以考慮貪心算法或動態規劃。
3.動態規劃的基本步驟
- 1.找出最優解的性質並刻劃其結構特徵
- 2.遞歸的定義最優值
- 3.以自底向上的方式計算出最優值
- 4.根據計算最優值得到的信息構造最優解(有時可以省略)
動態規劃特點:
4.經典例題講解
- 題目一:機器人一次可以走1m,2m或3m。編寫一個動態規劃算法求機器人走n米有多少種走法。
遞歸求解:
#include<stdio.h>
#define N 4
int robotSteps(int n){
if(n==1||n==0)
return 1;
else if(n==2)
return 2;
else return robotSteps(n-1)+robotSteps(n-2)+robotSteps(n-3);
}
int main(){
int n;
printf("一共有%d種走法!\n",robotSteps(N));
return 0;
}
動態規劃求解:
#include<stdio.h>
#define N 4
int robotSteps(int n){
int i,arr[N+1];
arr[1]=1;
arr[2]=2;
arr[3]=4;
for(i=4;i<n+1;i++){
arr[i]=arr[i-1]+arr[i-2]+arr[i-3];
}
return arr[n];
}
int main(){
int n;
printf("一共有%d種走法!\n",robotSteps(N));
return 0;
}
- 題目二:
子問題:列出所有情況可能出現的最優子結構,在將這些情況找出最優子結構。
遞歸解法:
遞歸求解重複計算太多。 - 動態規劃解決這個問題。
1.轉移方程
加一表示要一個硬幣。
2.初始條件和邊界情況
初始條件:就是用轉移方程算不出來的,需要手工定義。
3.計算順序
自頂向上,要讓要求得問題,其子問題都被求過。
public static int coinChange(int []A,int M) {
int [] f =new int[M+1];
int n = A.length;
f[0]= 0;
int i,j;
for(i=1;i<=M;++i) {
f[i]=Integer.MAX_VALUE;
for(j=0;j<n;++j) {
if(i>=A[j]&&f[i-A[j]]!=Integer.MAX_VALUE) {
f[i]=Math.min(f[i]-A[j]+1,f[i]);
}
}
}
if(f[M]==Integer.MAX_VALUE) {
f[M]=-1;
}
return f[M];
- 題目三(計數問題)
計算順序:
- 題目四(存在型)
輕鬆搞定動態規劃解決矩陣連乘問題
關注公衆號【輕鬆玩編程】,回覆“計算機資源”,“Java從入門到進階”,獲取更多學習資源!