關於動態規劃,你該了解這些!

2021-10-13 20:56:04 字數 2779 閱讀 1322

動態規劃,英文:dynamic programming,簡稱dp,如果某一問題有很多重疊子問題,使用動態規劃是最有效的。

所以動態規劃中每乙個狀態一定是由上乙個狀態推導出來的,這一點就區分於貪心,貪心沒有狀態推導,而是從區域性直接選最優的,

在關於貪心演算法,你該了解這些!中我舉了乙個揹包問題的例子。

例如:有n件物品和乙個最多能背重量為w 的揹包。第i件物品的重量是weight[i],得到的價值是value[i] 。每件物品只能用一次,求解將哪些物品裝入揹包裡物品價值總和最大。

動態規劃中dp[j]是由dp[j-weight[i]]推導出來的,然後取max(dp[j], dp[j - weight[i]] + value[i])。

但如果是貪心呢,每次拿物品選乙個最大的或者最小的就完事了,和上乙個狀態沒有關係。

所以貪心解決不了動態規劃的問題。

其實大家也不用死扣動規和貪心的理論區別,後面做做題目自然就知道了

而且很多講解動態規劃的文章都會講最優子結構啊和重疊子問題啊這些,這些東西都是教科書的上定義,晦澀難懂而且不實用。

大家知道動規是由前乙個狀態推導出來的,而貪心是區域性直接選最優的,對於刷題來說就夠用了。

上述提到的揹包問題,後序會詳細講解。

做動規題目的時候,很多同學會陷入乙個誤區,就是以為把狀態轉移公式背下來,照葫蘆畫瓢改改,就開始寫**,甚至把題目ac之後,都不太清楚dp[i]表示的是什麼。

這就是一種朦朧的狀態,然後就把題給過了,遇到稍稍難一點的,可能直接就不會了,然後看題解,然後繼續照葫蘆畫瓢陷入這種惡性迴圈中

狀態轉移公式(遞推公式)是很重要,但動規不僅僅只有遞推公式。

對於動態規劃問題,我將拆解為如下五步曲,這五步都搞清楚了,才能說把動態規劃真的掌握了!

一些同學可能想為什麼要先確定遞推公式,然後在考慮初始化呢?

因為一些情況是遞推公式決定了dp陣列要如何初始化!

後面的講解中我都是圍繞著這五點來進行講解。

可能刷過動態規劃題目的同學可能都知道遞推公式的重要性,感覺確定了遞推公式這道題目就解出來了。

其實 確定遞推公式 僅僅是解題裡的一步而已!

一些同學知道遞推公式,但搞不清楚dp陣列應該如何初始化,或者正確的遍歷順序,以至於記下來公式,但寫的程式怎麼改都通過不了。

後序的講解的大家就會慢慢感受到這五步的重要性了。

相信動規的題目,很大部分同學都是這樣做的。

看一下題解,感覺看懂了,然後照葫蘆畫瓢,如果能正好畫對了,萬事大吉,一旦要是沒通過,就怎麼改都通過不了,對 dp陣列的初始化,遞迴公式,遍歷順序,處於一種黑盒的理解狀態。

寫動規題目,**出問題很正常!

找問題的最好方式就是把dp陣列列印出來,看看究竟是不是按照自己思路推導的!

一些同學對於dp的學習是黑盒的狀態,就是不清楚dp陣列的含義,不懂為什麼這麼初始化,遞推公式背下來了,遍歷順序靠習慣就是這麼寫的,然後一鼓作氣寫出**,如果**能通過萬事大吉,通過不了的話就憑感覺改一改。

這是乙個很不好的習慣!

做動規的題目,寫**之前一定要把狀態轉移在dp陣列的上具體情況模擬一遍,心中有數,確定最後推出的是想要的結果

然後再寫**,如果**沒通過就列印dp陣列,看看是不是和自己預先推導的**不一樣。

如果列印出來和自己預先模擬推導是一樣的,那麼就是自己的遞迴公式、初始化或者遍歷順序有問題了。

如果和自己預先模擬推導的不一樣,那麼就是**實現細節有問題。

這樣才是乙個完整的思考過程,而不是一旦**出問題,就毫無頭緒的東改改西改改,最後過不了,或者說是稀里糊塗的過了

這也是我為什麼在動規五步曲裡強調推導dp陣列的重要性。

發出這樣的問題之前,其實可以自己先思考這三個問題:

如果這靈魂三問自己都做到了,基本上這道題目也就解決了,或者更清晰的知道自己究竟是哪一點不明白,是狀態轉移不明白,還是實現**不知道該怎麼寫,還是不理解遍歷dp陣列的順序。

然後在問問題,目的性就很強了,群裡的小夥伴也可以快速知道提問者的疑惑了。

注意這裡不是說不讓大家問問題哈, 而是說問問題之前要有自己的思考,問題要問到點子上!

大家工作之後就會發現,特別是大廠,問問題是乙個專業活,是的,問問題也要體現出專業!

如果問同事很不專業的問題,同事們會懶的回答,領導也會認為你缺乏思考能力,這對職場發展是很不利的。

所以大家在刷題的時候,就鍛鍊自己養成專業提問的好習慣。

這一篇是動態規劃的整體概述,講解了什麼是動態規劃,動態規劃的解題步驟,以及如何debug。

動態規劃是乙個很大的領域,今天這一篇講解的內容是整個動態規劃系列中都會使用到的一些理論基礎。

在後序講解中針對某一具體問題,還會講解其對應的理論基礎,例如揹包問題中的01揹包,leetcode上的題目都是01揹包的應用,而沒有純01揹包的問題,那麼就需要在把對應的理論知識講解一下。

大家會發現,我講解的理論基礎並不是教科書上各種動態規劃的定義,錯綜複雜的公式。

這裡理論基礎篇已經是非常偏實用的了,每個知識點都是在解題實戰中非常有用的內容,大家要重視起來哈。

今天我們開始新的征程了,你準備好了麼?

如果感覺對你有幫助,不要吝嗇給乙個?吧!

十 關於MySQL 標識列,你該了解這些!

又稱為自增長列 含義 可以不用手動的插入值,系統提供預設的序列值 特點 1 標識列必須和主鍵搭配嗎?不一定,但要求是乙個key 2 乙個表可以有幾個標識列?至多乙個!3 標識列的型別只能是數值型 4 標識列可以通過 set auto increment increment 3 設定步長 可以通過 手...

關於 c與c 知識點,你該了解這些 一

關於 c與c 知識點,你該了解這些 一 1.int a sizeof int sizeof a 求所儲存的位元組2.float aa a cout int aa endl 輸出a的數值 強制轉化為 int 注意格式3.float f2 3e2 3 10 2 float f3 3e 2 3 0.1 2...

關於位段,你應當了解這些

位段的成員可以是 int unsigned int signed int 或者是 char 屬於整形家族 型別 位段的空間上是按照需要以4個位元組 int 或者1個位元組 char 的方式來開闢的。位段涉及很多不確定因素,位段是不跨平台的,注重可移植的程式應該避免使用位段。位段的成員名後邊有乙個冒號...