簡單暴力到dp的優化(萌新篇)

2021-08-18 15:55:11 字數 4212 閱讀 9288

想寫一系列文章,總結一些題目,看看解決問題、優化方法的過程到底是什麼樣子的。

在數學上,斐波納契數列以如下被以

遞迴的方法定義:f(0)=0,f(1)=1, f(n)=f(n-1)+f(n-2)(n>=2,n∈n*)

根據定義,前十項為1, 1, 2, 3, 5, 8, 13, 21, 34, 55

給定乙個正整數n,求出斐波那契數列第n項(這時n較小)

解法一:最笨,效率最低,暴力遞迴,完全是抄定義。請看**

def f0(n):

if n==1 or n==2:

return 1

return f(n-1)+f(n-2)

分析一下,為什麼說遞迴效率很低呢?咱們來試著執行一下就知道了:比如想求f(10),計算機裡怎麼執行的?

每次要計算的函式量都是指數型增長,時間複雜度

o(2^(n/2))<=t(n)<=o(2^n),效率很低。效率低的原因是,進行了大量重複計算,比如圖中的f(8),f(7).....等等,你會發現f(8)其實早就算過了,但是你後來又要算一遍。

如果我們把計算的結果全都儲存下來,按照一定的順序推出n項,就可以提公升效率,斐波那契(所有的一維)的順序已經很明顯了,就是依次往下求。。

def f1(n):

if n==1 or n==2:

return 1

l=[0]*n

l[0],l[1]=1,1

for i in range(2,n):

l[i]=l[i-1]+l[i-2]

return l[-1]

時間複雜度o(n),依次往下打表就行,空間o(n).繼續優化:既然只求第n項,而斐波那契又嚴格依賴前兩項,那我們何必記錄那麼多值呢?記錄前兩項就行了

def f2(n):

a,b=1,1

for i in range(n-1):

a,b=b,a+b

return a

此次優化做到了時間o(n),空間o(1)附:這道題掌握到這裡就可以了,但是其實有時間o(log2n)的方法學習過線性代數的同學們能夠理解:

結合快速冪演算法,我們可以在o(log2n)內求出某個物件的n次冪。(在其它專題詳細講解)

注意:只有遞迴式不變,才可以用矩陣+快速冪的方法。

注:優化三可能只有在面試上或競賽中用,當然,快速冪還是要掌握的。

經過這個最簡單的斐波那契,大家有沒有一點感覺了?

好,我們繼續往下走

(補充:pat、藍橋杯原題,讓求到一萬多位,結果模乙個數。

可以每個結果都對這個數取模,否則爆記憶體,另:對於有多組輸入並且所求結果類似的題,可以先求出所有結果存起來,然後直接接受每乙個元素,在表中查詢相應答案)

乙隻青蛙一次可以跳上1級台階,也可以跳上2級。求該青蛙跳上乙個n級的台階總共有多少種跳法。

依舊是找遞推關係,分析:跳一階,就一種方法,跳兩階,它可以一次跳兩個,也可以乙個乙個跳,所以有兩種,三個及三個以上,假設為n階,青蛙可以是跳一階來到這裡,或者跳兩階來到這裡,只有這兩種方法。它跳一階來到這裡,說明它上一次跳到n-1階,同理,它也可以從n-2跳過來,f(n)為跳到n的方法數,所以,f(n)=f(n-1)+f(n-2)

和上題的優化二類似。

因為遞推式沒變過,所以可以用優化三

我們可以用2*1的小矩形橫著或者豎著去覆蓋更大的矩形。請問用n個2*1的小矩形無重疊地覆蓋乙個2*n的大矩形,總共有多少種方法?提示,大矩形看做是長度吧

請讀者自己先思考一下吧。。。仔細看題。。仔細思考

如果n是1,只有一種,豎著放唄;n是2,兩種:

n等於3,三種:

題意應該理解了吧?

讀到這裡,你們應該能很快想到,依舊是斐波那契式遞迴啊。

對於n>=3:怎麼能覆蓋到三?只有兩種辦法,從n-1的地方豎著放了一塊,或者從n-2的位置橫著放了兩塊唄。

和問題二的**都不用變。

給定乙個由0-9組成的字串,1可以轉化成a,2可以轉化成b。依此類推。。25可以轉化成y,26可以轉化成z,給乙個字串,返回能轉化的字母串的有幾種?

比如:123,可以轉化成

1 2 3變成abc,

12 3變成lc,

1 23變成aw,三種,返回三,

99999,就一種:iiiii,返回一。

分析:求i位置及之前字元能轉化多少種。

兩種轉化方法,一,字元i自己轉換成自己對應的字母,二,和前面那個數組成兩位數,然後轉換成對應的字母

假設遍歷到i位置,判斷i-1位置和i位置組成的兩位數是否大於26,大於就沒有第二種方法,f(i)=f(i-1),想反,等於f(i-1)+f(i-2)

注意:遞迴式不確定,不能用矩陣快速冪

(這幾個題放到這裡就是為了鍛鍊找遞迴關係的能力,不要只會那個爛大街的斐波那契)

'''

斐波那契問題:

斐波納契數列以如下被以遞迴的方法定義:

f(1)=1

f(2)=1

f(n)=f(n-1)+f(n-2)(n>=2,n∈n*)

'''#暴力抄定義,過多重複計算

def f0(n):

if n==1 or n==2:

return 1

return f(n-1)+f(n-2)

#記錄結果後依次遞推的優化,時間o(n)

def f1(n):

if n==1 or n==2:

return 1

l=[0]*n

l[0],l[1]=1,1

for i in range(2,n):

l[i]=l[i-1]+l[i-2]

return l[-1]

#既然嚴格依賴前兩項,不必記錄每乙個結果,優化空間到o(1)

def f2(n):

a,b=1,1

for i in range(n-1):

a,b=b,a+b

return a

簡單暴力到dp的優化(入門篇)

上篇,我們提到,遇到問題,首先根據定義寫出笨方法,找出依賴關係 有些題這一步就不太簡單,要自己歸納關係 然後進行優化,下面,我們通過幾道此方面的經典的,較為簡單的二維題目進行講解。開始根據題來說明 給定陣列arr,arr 中所有的值都為正數且不重複。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任...

hdu1579簡單的用dp優化遞迴

題目連線 include include include include include include const int inf 0x3f3f3f using namespace std int dp 110 n,a 110 110 sum 110 maxx int main for int i...

蒟蒻關於斜率優化DP簡單的總結

upd 這裡是yyb的更新,今天是2019.3.18的晚上。我覺我的這篇文章就是在扯蛋,所以到這裡看斜率優化把qwq。考試的時候被這個玩意弄得瑟瑟發抖 大概是yybgg的day4 小蒟蒻表示根本不會做.然後自己默默地搞了一下斜率優化 其實我講的會非常非常非常簡單,而且絕對沒有一張圖 因為我繪圖水平太...