如今有n塊黃金,每塊黃金的質量爲w[i],小明能夠一次性搬運質量不超過m的物體,問小明一次至多能運走多少質量的黃金?
對於該問題,閱讀過我以前講過的深度優先搜索應該不難寫出以下代碼。python
def dfs(cur, total, status = set()): for i in range(cur, n): if total + w[i] > m: continue status.add(total + w[i]) dfs(i+1, total + w[i]) return status
對於w = [1,8,6],m = 10的數據,能夠獲得status = {1,8,6,9,7},也就是w可以組合出的不超過m的全部值,取其最大值即爲該問題的答案。post
可是該解法的時間複雜度過高了,爲n!(這裏還與m值有關,要真有這麼大都別玩了),其實這裏能夠動態規劃,咱們如何應對更大n值的狀況?code
對於規模爲10的狀況,其複雜度在400w,而對於規模爲5的狀況,其複雜度在100,也就是說若是咱們可以把一個規模爲10的問題分解成兩個規模爲5的問題,那麼時間複雜度只須要100 + 100 = 200。速度較以前提高了2萬倍。get
那麼咱們如何經過兩個規模爲5的解得出規模爲10的解呢?io
def solution(n, m, w): def dfs(cur, end, total = 0, status = set()): for i in range(cur, end): if total + w[i] > m: continue status.add(total + w[i]) dfs(i+1, end, total + w[i]) return status ans1 = sorted(list(dfs(0, n//2))) ans2 = sorted(list(dfs(n//2, n))) ans = max(ans1) for i in ans2: t = binary_search_last_equal_or_lower(m-i, ans1) ans = max(ans, t+i) return ans
上述代碼中,咱們遍歷ans2列表,在ans1尋找最大的且與i相加不超過m的值(反過來也行),並在遍歷的過程當中動態更新ans的值,遍歷結束,ans即咱們想要的答案。ast
對於最終的ans,有以下三種可能。class
其中狀況1在遍歷時完成,狀況2在ans賦初值時完成,狀況3在ans1沒有值能夠與m-i結對時完成(這時候二分查找返回0值)。搜索
本文示例題目與acwing 171.送禮物一致,讀者可自行嘗試提交,驗證本身代碼的正確性。遍歷