動態規劃經典問題總結

2021-08-20 13:52:56 字數 3831 閱讀 1566

假設有幾種硬幣,如1、3、5,並且數量無限。請找出能夠組成某個數目的找零所使用最少的硬幣數。

這是一道經典的動態規劃方法,我們可以維護乙個一維動態陣列dp,其中dp[i]表示錢數為i時的最小硬幣數的找零,遞推式為:dp[i] = min(dp[i], dp[i - coins[j]] + 1);

其中coins[j]為第j個硬幣,而i - coins[j]為錢數i減去其中乙個硬幣的值,剩餘的錢數在dp陣列中找到值,然後加1和當前dp陣列中的值做比較,取較小的那個更新dp陣列。

class solution }}

return dp[amount] > amount ? -1 : dp[amount];}};

假設有幾種硬幣,每個值代表一張錢的面值,再給定乙個整數代表要找的錢數,求換錢有多少種方法。

乙個硬幣乙個硬幣的增加,每增加乙個硬幣,都從1遍歷到amount,對於遍歷到的當前錢數j,組成方法就是不加上當前硬幣的頻發dp[i-1][j],還要加上,去掉當前硬幣值的錢數的組成方法,當然錢數j要大於當前硬幣值,那麼我們的遞推公式為:dp[i][j] = dp[i - 1][j] + (j >= coins[i - 1] ? dp[i][j - coins[i - 1]] : 0)

注意我們要初始化每行的第乙個位置為1。

class solution 

}return dp[coins.size()][amount];}};

擴充套件:

乙個矩形區域被劃分為n*m個小矩形格仔,在格仔(i,j)中有a[i][j]個蘋果。現在從左上角的格仔(1,1)出發,要求每次只能向右走一步或向下走一步,最後到達(n,m),每經過乙個格仔就把其中的蘋果全部拿走。請找出能拿到最多蘋果數的路線。

分析:這道題中,當前位置(i,j)是狀態,用m[i][j]來表示到達狀態(i,j)所能得到的最多蘋果數,那麼m[i][j] = max(m[i-1][j],m[i][j-1]) + a[i][j] 。特殊情況是m[1][1]=a[1][1],當i=1且j!=1時,m[i][j] = m[i][j-1] + a[i][j];當i!=1且j=1時m[i][j] = m[i-1][j] + a[i][j]。

給定兩個字word1和word2,找到將word1轉換為word2所需的最小步驟數。 (每個操作計為1步)。

您對單詞允許以下3種操作:

a)插入字元

b)刪除字元

c)替換字元

dp[i][j]指把word1[0..i - 1]轉換為word2[0..j - 1] 的最小運算元。

邊界條件:

dp[i][0] = i; 從長度為 i 的字串轉為空串 要刪除 i 次

dp[0][j] = j. 從空串轉為長度為 j 的字串 要新增 j 次

一般情況:

如果word[i - 1] == word2[j - 1],則dp[i][j] = dp[i - 1][j - 1],因為不需要進行操作,即運算元為0.

如果word[i - 1] != word2[j - 1],則需考慮三種情況,取最小值:

replace word1[i - 1] by word2[j - 1]: (dp[i][j] = dp[i - 1][j - 1] + 1 (for replacement));

delete word1[i - 1]: (dp[i][j] = dp[i - 1][j] + 1 (for deletion));

insert word2[j - 1] to word1[0..i - 1]: (dp[i][j] = dp[i][j - 1] + 1 (for insertion)).

class solution 

}return dp[row][col];}};

擴充套件:

(1)子串匹配

void cal_next(char *str, int *next, int len)

if (str[k + 1] == str[q])//如果相同,k++

next[q] = k;//這個是把算的k的值(就是相同的最大字首和最 大字尾長)賦給next[q]

}}int kmp(char *str, int slen, char *ptr, int plen)

}return -1;

}

假如s1的最後乙個元素 與 s2的最後乙個元素相等,那麼s1和s2的lcs就等於 與 的 lcs 再加上 s1和s2相等的最後乙個元素。

假如s1的最後乙個元素 與 s2的最後乙個元素不等,那麼s1和s2的lcs就等於 : 與 s2 的lcs, 與 s1 的lcs 中的最大的那個序列。

訪問到每個點的時候,以該點為子串行的末尾的乘積,要麼是該點本身,要麼是該點乘以以前一點為末尾的序列,注意乘積負負得正,故需要記錄前面的最大最小值。

dp1[i]:以第i個數結尾的連續子串行最大乘積

dp2[i]:以第i個數結尾的連續子串行最小乘積

轉移方程:

dp1[i]=max(data[i],dp1[i-1]*data[i],dp2[i-1]*data[i]);

dp2[i]=min(data[i],dp1[i-1]*data[i],dp2[i-1]*data[i]);

double func(double *a,const int n)  

return

value;

}

經典動態規劃問題總結

動態規劃引入 首先我們以乙個最基本的例子來分析 菲波那切數列。我們都知道,菲波那切數列的遞推公式f n f n 1 f n 2 這裡我就說明一般情況,不列舉邊界條件了 很簡單,如果我們用遞迴的方法來求解f n 兩三行 就出來了。那麼我們深入分析一下這樣有什麼問題?f 2 f 1 f 0 f 3 f ...

動態規劃經典問題

from 實現在 維基百科對動態規劃的定義 動態規劃 英語 dynamic programming,簡稱dp 是一種在數學 電腦科學和經濟學中使用的,通過把原問題分解為相對簡單的子問題的方式求解複雜問題的方法。動態規劃常常適用於有重疊子問題 1 和最優子結構性質的問題,動態規劃方法所耗時間往往遠少於...

動態規劃經典問題

子串 在給定的字串中選取連續的一段 子串行 可以不連續,但是要保證出現的順序與原字串相同 比如字串abcdefg abc既是子串又是子串行 acd只是子串行 一 最大連續子串行和 給定乙個整數序列a1,a2 an。求最大的連續的子串行的和。比如的最大連續子串行的和為5 3 1 1 2 萬能列舉?每次...