日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

简单暴力到dp的优化(入门篇)

發(fā)布時間:2023/12/13 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 简单暴力到dp的优化(入门篇) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

上篇,我們提到,遇到問題,首先根據(jù)定義寫出笨方法,找出依賴關系(有些題這一步就不太簡單,要自己歸納關系),然后進行優(yōu)化,下面,我們通過幾道此方面的經(jīng)典的,較為簡單的二維題目進行講解。

?

開始根據(jù)題來說明:

第一個萌新題

給定數(shù)組arr, ?arr ?中所有的值都為正數(shù)且不重復。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意張, ?再給定一個整數(shù)aim 代表要找的錢數(shù),求組成aim 的最少貨幣數(shù)。

??[舉例]

??arr=[5,2,3], ?aim=20。

??4 張5 元可以組成20 元,其他的找錢方案都要使用更多張的貨幣,返回4。

arr=[5,2,3], ?aim=0。

??不用任何貨幣就可以組成0 元,返回0。

??arr=[3,5],aim=2。

??根本無法組成2 元,錢不能找開的情況下默認返回-1。

(你要是想貪心就貪吧,反正我不貪)

定義f(a,b)代表的是a面值及之前的貨幣,組成b元的最少張數(shù)。那f(arr[-1],aim)就是我們想求的答案。現(xiàn)在分析,怎樣通過前面的狀態(tài)推出結(jié)果?對于貨幣arr[-1],我們可以一張都不用,那最少張數(shù)其實就是f(arr[-2],aim),我們也可以用一張arr[-1],最少張數(shù)就可能是f(arr[-2],aim-arr[-1])+1(用之前的錢組成aim-arr[-1]元錢,然后加一張arr[-1]),同理,我們可以用兩張arr[-1],或者更多,直到下一個就超過aim的時候。所以我們應該在所有情況中選最小的,

歸納表達式:

f(a,b)=min(f(arr[a-1],b-k*arr[a])+k),k>=0,且b-k*arr[a]>=0

當然,以前也提到過,直接遞歸我們會有大量重復計算,所以需要記下來之前的結(jié)果供我們使用。有兩個參數(shù)代表現(xiàn)在的狀態(tài),所以生成二維表。

l=[[0 for i in range(len(arr))] for i in range(aim+1)]#

我們看,f(arr[a],b)和誰有關?和上一行,也就是arr[a-1]那一行的很多左邊元素有關。

所以確定打表順序,從上到下,從左到右,打表,一個一個打,l[a][b]=min(f(a-1,b-k*arr[a])+k),依次推出l[a][b],右下角就是答案。

?

?

?

但是,還是有相當多的重復計算,我們的l[a][b-arr[a]]其實就是根據(jù)除了l[a-1][b]的左邊那些元素求的的最小值

所以l[a][b]=min(l[a][b-arr[a]]+1,l[a-1][b])。

?

其實和左邊和上邊元素相關的背包,還有一些別的題,都是如此。對于本物品,當前決策就是拿或不拿,以前的最優(yōu)情況

l[a][b-arr[a]]l[a-1][b]已經(jīng)有了。不用管的。結(jié)合當前狀態(tài)的定義,就明白了。

?

至此,時間優(yōu)化到嚴格o(a*b),空間o(a*b),空間還能優(yōu)化到o(min(a,b)),下一個題講壓縮方法。

第二個萌新題

給一個由數(shù)字組成的矩陣,初始在左上角,要求每次只能向下或向右移動,路徑和就是經(jīng)過的數(shù)字全部加起來,求可能的最小路徑和。

1 ?3 ?5 ?9

8 ?1 ?3 ?4

5 ?0 ?6 ?1

8 ?8 ?4 ?0

路徑:1 3 1 0 6 1 0路徑和最小,返回12

生成和矩陣相同大小的二維表DP,用來記錄當前的最小路徑和

(以后也不分析暴力的時間復雜度了)

對于普遍的位置i,j,只有i-1,j和i,j-1這兩個位置可以一步走到這里,所以

DP[i,j]=min(DP[i,j-1],DP[i-1,j])+L[i,j]

壓縮:我們發(fā)現(xiàn),除了這個位置上本身的數(shù),DP[i,j]只和DP表中左邊和上邊的值有關,所以可以生成長度為矩陣較小邊長一維表,用兩層循環(huán)。注意順序,從左向右打表,只有這樣,左邊的那個元素才是被更新過的,才是本行的左邊那個元素。

最左邊的DP值是直接累加的,其他位置

For i 0 to 高度:

????For j 0 to 寬度

DP[j]=min(DP[j-1],DP[j])+L[i,j]

時間不變,空間優(yōu)化到o(較小邊長)

?

?第三道萌新題

題干和第一題一樣,請返回所有的還錢方法有多少種

經(jīng)過一二題,應該自己會做了。

(請記住:一般問方法的題目,只需把式子中max或者min改為sum即可)

n=int(input()) dp=[0]*(n+1) dp[0]=1 tmp=[1,5,10,20,50,100] for kk in tmp:for i in range(kk,n+1):dp[i]+=dp[i-kk] print(dp[n])

?

總結(jié)

以上是生活随笔為你收集整理的简单暴力到dp的优化(入门篇)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。