學習動態規劃DP(一) DAG模型

2021-08-20 11:20:21 字數 2348 閱讀 7362

之前初學了一點關於動態規劃的知識,但沒有系統的學習,最近在空閒時間根據紫書(演算法競賽入門經典)開始了比較有計畫的學習,先寫下這篇部落格,作為筆記。

一、我對動態規劃的看法。

動態規劃,即是把原問題劃分為各個規模更小的問題去解決,原問題的最優解包括了各個子問題的最優解(感覺本質上是分治法)。所以動態規劃用於求解最優值,解題過程中最重要的是確定好狀態轉換方程。對於動態規劃的學習,我覺得需要知道的基礎概念不多,就是了解了動態規劃的想法,然後就是做題訓練了,從題目中學習dp才比較有效率。

二、一般的解題思路、步驟。

1、定義狀態:乙個狀態遵循什麼規則需要我們自己定義,我們可以通過定義不同的規則來定義不同的狀態,但要寫出每乙個狀態的轉移方程的難度不同,所以需要我們有目的的篩選,這就需要從題目訓練中學習。通過量的累積達到質的變化。

2、判斷乙個狀態有幾種可能的決策:在遵循自己對狀態所定義的規則的條件下,確保對條件的列舉不存在缺漏的情況下,列舉出某一狀態下可能出現的不同決策,即各種可能的狀態轉變方向。

3、根據不同的決策列出對應的狀態轉移方程:狀態轉移方程需要確保可以得到最優的結果並且對各種可能出現的情形沒有漏舉的情況。

三、如何定義狀態

做了一些題,我發現對狀態的定義,我們都是用陣列來表示,可能是一維陣列,也可能是多維陣列。陣列的維度根據不同的題目要求而定,有時可以有多解,就是可以用不同維度的陣列來解題,但這種情況下一般多維的解題陣列可以降維到最簡。下面還是通過一些基礎、經典的例題來說明。

四、dp例題(一下兩題都是紫書的,暫時找不到具體**)

dag模型(dag——有向無環圖):即是把動態規劃的題目的解題轉為有向無環圖去解題。

1、矩形巢狀

題目描述:有n個矩形,每乙個矩形可以用兩個整數a、b描述表示長和寬,如矩形x(a,b)。矩形可以90°旋轉。當乙個矩形的長和寬都分別嚴格小於另乙個矩形的長和寬時,該矩形可以巢狀在另乙個矩形之中。如(1,5)可以巢狀在(2,6)中,但不可以巢狀在(3,4)中。要求選出盡量多的矩形排成一行,使得除了最後乙個之外,每乙個矩形都可以巢狀在下乙個矩形之內。如果有多解,矩形編號的字典序應該盡量的小。

分析:乙個矩形要巢狀在另乙個矩形中需要有一點的條件(前乙個矩形較長的一條邊小於後乙個矩形的較長的一條邊,以及前乙個矩形較短的一條邊小於後乙個矩形的較短的一條邊),這樣可以把前後兩個矩形看成兩個不同的節點,前乙個矩形巢狀在後乙個矩形裡,看成有一條從後乙個矩形指向前乙個矩形的有向邊。這樣就可以把問題轉換為求解有向圖的最長路且這個有向圖是無環的,即dag。

要求最長路,我們可以定義乙個狀態,如 d[i] 表示從結點 i 出發的最長路長度,這樣的話可以求出,狀態轉移方程為 d[i] = max(d[i],d[j]+1),其中 j 是結點 i 的下乙個結點,即存在一條有向邊從 i 指向 j。

為什麼狀態轉換方程是這樣呢?首先在每乙個當前狀態下,我們只有一種決策可行,就是前往下乙個,即使下乙個點有多種選擇,但本質上都一樣,就是要前往下乙個點。然後將當前狀態和下乙個狀態比較,d[i]表示從結點 i 出發的最長路徑,因為存在從 i 到 j 的有向邊,所以如果從結點 j 出發的最長路徑加上從 i 到 j 之間的路徑的和得到的新的路徑比原來從結點 i 出發的最長路徑還長,那麼我們就更新從結點 i 出發的最長路徑長度,也就得出了上面的狀態轉移方程。因為每乙個結點我們都和與它相連的結點相比較,所以最終得出的是最優結果。

(關於狀態的選取,我覺得還是需要多做題從題目中學習,以後自己做的時候才會有比較清晰的思路)

**:

#include #include #include using namespace std;

const int maxn=1e3+5;

// g[i][j]為鄰接矩陣,表示一張圖,這張圖上有從 i 到 j 的有向邊

// d[i]為狀態陣列

int g[maxn][maxn],d[maxn],n;

//記錄矩形的資訊

struct rec

rec[maxn];

int dp(int i)

//按最小字典序輸出最優決策下的矩形編號

//選取最大的 d[i] 對應的 i ,如果有多個 i,則選擇最小的i 才能保證字典序最小

void print(int i)

//同時求最大最小值

void max_min()

cout*/}

小結:

個人感覺學習動態規劃,涉及的知識挺多的,最好是一次學習一種題型,然後自己做好歸納。比如這類題型的狀態一般怎麼定義,可以用什麼模型去做等。比如上面的兩道例題都是跟dag最長最短路有關,對於這種題型,一般可以定義兩種狀態:

(1)設d[i]為從 i 出發的最長路,則d[i]=max((i,j)∈e)。

(2)設d[i]為以 i 結束的最短路,則d[i]=min((j,i)∈e)。

然後就是刷題,題做多了,我感覺對動態規劃的理解會自然而然的深。

動態規劃 DAG模型

有n個矩形,每個矩形可以用a,b來描述,表示長和寬。矩形x a,b 可以巢狀在矩形y c,d 中當且僅當a c,b d或者b c,a d 相當於旋轉x90度 例 1,5 可以巢狀在 6,2 內,但不能巢狀在 3,4 中。你的任務是選出盡可能多的矩形排成一行,使得除最後乙個外,每乙個矩形都可以巢狀在下...

動態規劃 DAG模型

dag 有向無環圖 上的動態規劃是學習動態規劃的基礎。有n個矩形,每個矩形可以用a,b來描述,表示長和寬。矩形x a,b 可以巢狀在矩形y c,d 中當且僅當a c,b d或者b c,a d 相當於旋轉x90度 例 1,5 可以巢狀在 6,2 內,但不能巢狀在 3,4 中。你的任務是選出盡可能多的矩...

動態規劃 DAG模型 硬幣問題

題目 有n種硬幣,面值分別為v1,v2,vn,每種都有無限多。給定非負整數s,可以選用多少個硬幣,使得面值之和恰好為s?輸出硬幣數目的最小值和最大值!dag問題的動態規劃求解 includeusing namespace std typedef long long ll typedef long d...