動規解題的一般思路 演算法學習

2021-10-04 08:38:15 字數 1745 閱讀 3488

該思路來自於北大郭煒老師

微博:遞迴函式有n個引數,就定義乙個n維的陣列,陣列

的下標是遞迴函式引數的取值範圍,陣列元素的值

是遞迴函式的返回值,這樣就可以從邊界值開始,

逐步填充陣列,相當於計算遞迴函式值的逆過程。

第一步:原問題分解為子問題

 把原問題分解為若干個子問題,子問題和原問題形式相同

或類似,只不過規模變小了。子問題都解決,原問題即解

決(數字三角形例)。

 子問題的解一旦求出就會被儲存,所以每個子問題只需求

解一次。

第二步:確定狀態

在用動態規劃解題時,我們往往將和子問題相

關的各個變數的一組取值,稱之為乙個「狀

態」。乙個「狀態」對應於乙個或多個子問題,

所謂某個「狀態」下的「值」,就是這個「狀

態」所對應的子問題的解。

所有「狀態」的集合,構成問題的「狀態空間」。「狀態

空間」的大小,與用動態規劃解決問題的時間複雜度直接相關。

在數字三角形的例子裡,一共有n×(n+1)/2個數字,所以這個

問題的狀態空間裡一共就有n×(n+1)/2個狀態。

整個問題的時間複雜度是狀態數目乘以計算每個狀態所需

時間。在數字三角形裡每個「狀態」只需要經過一次,且在每個

狀態上作計算所花的時間都是和n無關的常數。

用動態規劃解題,經常碰到的情況是,k個整型變數能

構成乙個狀態(如數字三角形中的行號和列號這兩個變數

構成「狀態」)。如果這k個整型變數的取值範圍分別是

n1, n2, ……nk,那麼,我們就可以用乙個k維的陣列

array[n1] [n2]……[nk]來儲存各個狀態的「值」。這個

「值」未必就是乙個整數或浮點數,可能是需要乙個結構

才能表示的,那麼array就可以是乙個結構陣列。乙個

「狀態」下的「值」通常會是乙個或多個子問題的解。

第三步:確定一些初始狀態(邊界狀態)的值

以「數字三角形」為例,初始狀態就是底邊數字,值

就是底邊數字值。

第四步

確定狀態轉移方程

定義出什麼是「狀態」,以及在該 「狀態」下的「值」後,就要

找出不同的狀態之間如何遷移――即如何從乙個或多個「值」已知的

「狀態」,求出另乙個「狀態」的「值」(「人人為我」遞推型)。狀

態的遷移可以用遞推公式表示,此遞推公式也可被稱作「狀態轉移方

程」。

數字三角形的狀態轉移方程:

能用動規解決的問題的特點1:

問題具有最優子結構性質。如果問題的最優解所包含的

子問題的解也是最優的,我們就稱該問題具有最優子結

構性質。

2無後效性。當前的若干個狀態值一旦確定,則此後過程

的演變就只和這若干個狀態的值有關,和之前是採取哪

種手段或經過哪條路徑演變到當前的這若干個狀態,沒

有關係。

動態規劃解題一般思路

摘自mooc的程式設計與演算法 一.遞迴到動規的轉換方法 遞迴函式有n個引數,就定義乙個n維的陣列,陣列的下標就是遞迴函式引數的取值範圍,陣列元素的值就是遞迴的返回值,這樣就可以從邊界值開始逐步填充陣列,相當於計算遞迴函式值的逆過程 二.動態規劃解題一般思路 1.將原問題分解成子問題 把原問題分解成...

樹形DP一般解題思路

注意先求下屬,再求上司。利用鏈式前向星儲存樹 p1352 沒有上司的舞會 include using namespace std const int maxn 6e3 10 int n,r maxn head maxn int cnt 邊的編號 int d maxn 統計編號節點父節點的個數 int...

動態規劃解題的一般思路

遞迴到動規的一般轉化方法 遞迴函式有n個引數,就定義乙個n維的陣列,陣列的下表是遞迴函式引數的取值範圍,陣列元素的值是遞迴函式的返回值,這樣就可以從邊界值開始,逐步填充陣列,相當於計算遞迴函式值的逆過程 動規解題的一般思路 1.將原問題分解為子問題 把原問題分解為若干個子問題,子問題和原問題形式相同...