動態規劃階段性總結(一)

2021-10-07 12:55:08 字數 3152 閱讀 7505

這裡說一下動規的基本思想,本思想僅僅截止於2020.6.26日,今後我如果對動規有新理解,將會持續更新。

首先動規講究兩個原則:

(我感覺目前我自己對這兩個原則理解還不是很深刻,因為做的題還不夠,就僅僅講講目前的理解,以作為記錄)

1、最優化原則

一本通上有一句話說的很好:

乙個問題的區域性最優將導致整個問題最優

動態規劃我目前遇到的題基本上都是用來解決最優解問題,例如找出最少花費啊,最優路徑啊等等等等。而在解題的過程中,肯定是一步步求解,每一步就相當於乙個子問題,在做題時你就會發現,你的每個子問題也是按著最優解去求的,所以最終的結果一定是最優的。

此處必須要提一下貪心法,有的小夥伴(包括我)之前也一直認為貪心法的每一步也是最優解,因為每次都會去找乙個最好的嘛,但其實不然,貪心的區域性看似最優,但最後往往得不到整體最優,所以侷限性很大。具體與貪心的區別我以後大概會寫吧

2.無後效性原則

一本通上又一句話說得好:

某階段的狀態一旦確定,則此後的過程演變不再受此前各狀態及決策的影響

我的理解是什麼呢,就是某乙個決策一旦確定,那麼你的這個決策一定是最優的,且對整體而言也是最優的,你以後的資料,決策絕對不會對之前的決策有任何的影響,但是你的之前的這個決策會對後面你即將做出的決策產生影響,這是一定的,畢竟一步步算嘛,前人鋪路,後人乘涼嘛。

簡單地說,決策一旦下達,便是一錘定音,不會再更改

如果你在寫動規的過程中,遇到了前後決策糾纏不清的情況,大概要重新梳理一下思路了。

以下題目來自奧賽一本通,評測**:

1、數字金字塔【題目描述】

觀察下面的數字金字塔。寫乙個程式查詢從最高點到底部任意處結束的路徑,使路徑經過數字的和最大。每一步可以從當前點走到左下方的點也可以到達右下方的點。

在上面的樣例中,從13到8到26到15到24的路徑產生了最大的和86。

【題目描述】

第乙個行包含r(1≤ r≤1000),表示行的數目。

後面每行為這個數字金字塔特定行包含的整數。

所有的被**的整數是非負的且不大於100。

【輸出】

單獨的一行,包含那個可能得到的最大的和。

【輸入樣例】

5

1311 8

12 7 26

6 14 15 8

12 7 13 24 11

【輸出樣例】

哈哈

這個題可有意思了,作為入門引例真的再合適不過了

首先第一想法是不是貪心法亞

對嘛,我每一次都選個大的加上去,結果不就大了嗎!

很遺憾,不對呀 阿sir~~

你康康,加入從第乙個開始,每一次向下都選擇數字最大的,那麼就是

13 --> 11 --> 12 --> 14 -->13 == 63 < 86

不對呀,是吧。所以看來只能用動態規劃了。

這道題告訴我們做人不要貪心亞,只顧眼前利益而不看長遠,這定律感覺在各個領域都適用呢~~

那麼問題來了,動態規劃怎麼搞呢?

這裡我說一下正推法,至於倒退法請讀者(我自己)自己去想!!!!(想不明白看書!!)

首先 我們要設立乙個陣列b[i][j],存放乙個很關鍵的東西:

當前決策的最優解的值

然後我們一步一步看

當我們從最頂部開始:13 此時沒有別的點,就他乙個,那麼此時最優解就是他自己b[1][1]=13

然後看第二層:11 和 8 此時兩者都只連線了乙個 13 所以此時這兩個點的最優解 是他們自己的值加上之前確定好的最優值13

b[2][1]=13+11=24

b[2][2]=13+8=21

然後第三層

12這個點,只有一條路到達他 所以b[3][1]=b[2][1]+12=45

7這個點,有兩條路可以到達他 由於之前的決策已經確定,一定為最優解,所以選擇乙個最大的即可:b[3][2]=b[2][1]+7=31

(有同學可能會問了,這裡你也是選最大的啊,為啥就不叫貪心法了呢?這裡最大的區別就是上面的決策是已經確定好了的最優解,所以我敢直接加上去,這就是最微妙之處,請你後來看的時候務必細細體會這裡,這裡就是利用了無後效性原則,我敢加就是因為我知道後面的決策不會對前面有影響,但貪心就不一樣了,後面的可能就會對前面造成影響,使其不是最優解)

26這個點,也只有一條路可以到達

b[3][3]=b[2][2]+26=47

按著這個思想,一步一步向下類推,最後的最大值就是答案咯

下面上**啦!(你一定能看明白的w!!! )

#include

#include

#include

#include

#include

using

namespace std;

intmain()

}for

(int i=

2;i<=n;i++

)else}}

int temp;

for(

int i=

1;i<=n;i++)}

cout<

/*cout

int t=1;

for(int i=2;i<=n-1;i++)

cout

這裡小小總結一下:

如果你覺得這個題能用動規做,那麼一定就能找到乙個最原始的乙個部分,他的最優值是已經確定下來的,作為第一步決策,就像上面題中的第乙個點13,然後再順著一步一步的走下去。

另外,所給資料一定是有順序的,或者是可以排序的,這樣你才能寫迴圈一步一步去求解。

(還有乙個最長不下降子串行的題目,今天太晚了,明天寫!!!!! )

ACM 階段性總結 ACM 動態規劃 DP

這短時間看了 揹包九講 看到揹包問題解法中的優美之處也看到揹包問題在現實中的應用,總結出一句話 揹包問題值得一看。揹包問題可以概括為這樣的模型 有若干種選擇,每種選擇有一定的代價和價值,做某些選擇會得到特定的狀態,問我們在約定的條件下怎麼得到特定的狀態?這裡的狀態可以是代價和或者價值和或者由其他這兩...

階段性總結

今天聽學長交流了一些人生的經驗,便有了一些感觸,加上對自己最近的學習狀態的總結,就寫一篇部落格給自己一點指示。最近渾渾噩噩的,有幾次考試也沒考好,考後也沒總結。晚自習本想刷一些題,複習一下,或是學習一點技術。看見其他同學在打擺,便動搖了。最後心中也只是徒留深深的罪惡感。所以我也是時候對自己的未來進行...

階段性總結

感覺上個星期還挺痛苦的,因為要練演算法,每個人都告訴我說演算法很重要很重要,但是演算法對我來說就像是一根很亂的神經,一觸就炸了,可我的驕傲還不允許我放棄。在leetcode上練習的時候是直接告訴用什麼方法,在寫藍橋杯演算法的時候就像是閱讀理解,經常讀不懂是什麼意思,要不就是理解錯誤,追根究底還是做的...