一道簡單DP題

2021-09-29 15:41:31 字數 1178 閱讀 5772

首先,一看就應該知道這是一道dp題。原因在於其當前結果都依賴於前面計算得到的子結果。區分分治和dp的關鍵條件就在於演算法執行中間階段的計算結果是否依賴於其子問題的結果,若依賴則為dp,否則為分治。

dp題的關鍵在於找出狀態轉移方程和初始條件(或者稱為邊界值)。找出狀態轉移方程的關鍵又在於找對乙個狀態函式。根據我目前的經驗,這種狀態一般都是乙個區域性最優結果,如本題就可以設f(k)為前k-1項結果的最大值

下一步,我習慣先找狀態轉移方程,再根據狀態轉移方程找出邊界條件的值。很容易想到,狀態轉移方程為f(k)=max(f(k-2)+ak,f(k-1))。這其實意味著第k個元素是否取得,max函式中前者代表取,後者代表不取。這裡的技巧感覺只能慢慢體會,別人講恐怕也只能講到這個地步了。

進而,可以看出,在k=1時,k-2為-1,k-1為0。這裡不從k=2開始遍歷,是因為未必第1(從0開始)個元素取還是不取(這取決於a0和a1的相對大小),這裡也算是乙個坑吧。

f(-1)和f(0)的取值顯而易見。特別是f(-1),這種下標不在正常範圍裡的,一般都是特殊值,如0、1,這取決於題目具體要求解的是什麼。

確定了狀態轉移方程和邊界條件後,就可以很容易地得到以下**。

int

rob(vector<

int>

& v)

return t[l]

;}

另外,最開始對特殊情況的判斷也是乙個坑,只要題目沒有明確說明「不為空」「>0」之類的字眼,在**開頭加入一些特殊情況的判斷還是非常有必要的,只不過我經常會忘記……

vector五種建構函式參見【stl】vector的五種建構函式。stl的使用還是要非常熟練才行。

先直接看**。

int

rob(vector<

int>

& v)

return cur;

}

這裡最奇妙的技巧就是只使用了兩個變數,讓原本為o(n)的空間複雜度降為了o(1)。這裡充分利用了計算當中只依賴於前面兩種情況的特性。這裡可以推而廣之,如果狀態轉移方程中只涉及前面兩種區域性結果,那麼都可以採用這種減少空間複雜度的方法。

198. 打家劫舍

記一道DP題

給定 n l r 求長度為n的 且元素在 l r 的 且 陣列元素和是3的倍數的 陣列的 個數 dpmod0 表示區間內的數mod 3 0的個數 mod1 mod2 同理 dp i j 表示 長度為i的 陣列元素mod 3 為 j 的陣列的個數 如果 i 1長度的陣列和 mod 3 0 那麼我再加乙...

DP 一道遞推題。。。

bob想要構造一張由n個節點構成的圖。構造的過程由兩步組成 首先bob會取出n個孤立的點,並把它們從1到n編號,然後對每個節點用一種顏色染色,bob一共可以使用k種不同的顏色。接下來bob會在這張圖中加入一些有向邊,對於每乙個編號範圍在 2,n 的節點i,bob有可能選擇乙個節點j滿足j i並且節點...

樹形dp 的 一道巨簡單題

這三個字寫這麼大完全是為了提醒自己 hhhh 竟然這都不會 樹形dp 不懂得如何推出狀態表示式 即使再簡單 看見題目就無從下手!有點煩 所以決定多刷一點dp題,先看了最基礎的 洛谷p1352 這個題其實挺簡單的,但是我是真的廢。題意 給出一棵樹,每個節點有自己的權值,選擇出一些點,選擇點的時候如果選...