三道題理解動態規劃

2021-07-27 02:17:50 字數 3289 閱讀 5984

動態規劃是演算法導論中介紹的最重要的幾種基本演算法之一,因為好長時間沒有看書,再加上原來就理解的不深入,所以早就忘的差不多了,這兩天正好因為一道面試題複習一下。

用幾句話描述動態規劃問題如下:

乙個問題可以分解若干子問題,每乙個子問題為一種狀態,求出每乙個狀態的最優解,進而在它的幫助下求出下乙個狀態的最優解。

解決動態規劃問題,最重要的步驟就是找出狀態轉移方程。有了狀態轉移方程就可以根據初始狀態(邊界)求出每乙個狀態的最優解。

動歸問題的特點如下:

下面用三道題目幫組理解一下。

有1分,3分,5分3種硬幣,如何使用最少的硬幣數量得到12分。這個題目的狀態轉移方程如下。

d(i) = min(d(i-v(j)) + 1)

其中d是硬幣數量,i是money總數,v(j)是第j個硬幣的單位。初始值d(0)=0。**如下:

#! /usr/bin/env python

# -*- coding:gbk -*-

class

solution

(object):

defget_min_count

(self, money, item_list):

num_list = {}

if money == 0:

return

0 num_list[0] = 0

for i in range(1, money + 1):

min = (1

<<31) - 1

index = -1

for j in range(0, len(item_list)):

if item_list[j] <= i:

if min > num_list[i - item_list[j]] + 1:

min = num_list[i - item_list[j]] + 1

index = j

print

"cur_index:%d cur_item:%d pre_index:%d pre_num:%d" \\

%(i, item_list[index], i - item_list[index], num_list[i - item_list[index]])

num_list[i] = min

return num_list[money]

if __name__ == "__main__":

s = solution()

money = 12

item_list = [1, 3, 5]

print s.get_min_count(money, item_list)

題目的意思就是從乙個數列當中找出最長的公升序的子數列,比如」123412345123」的最長公升序子數列是」12345」,這個題目的狀態轉移方程如下。

d(i) = d(i)+1 [if a[i] > a[j] i > j] or d(i) = 1 [if a[i] < a[j] i > j]

其中d是長度,i和j分別代表第i和j個字元,初始值d(0)=0。**如下:

#! /usr/bin/env python

# -*- coding:gbk -*-

class

solution

(object):

defmax_up_seq

(self, seq):

if len(seq) == 0:

return

0 ret_len = {}

ret_len[0] = 1

max_len = 1

max_seq_start = 0

for i in range(0, len(seq) - 1):

if seq[i + 1] >= seq[i]:

ret_len[i+1] = ret_len[i] + 1

else:

ret_len[i+1] = 1

if max_len < ret_len[i]:

max_len = ret_len[i]

max_seq_start = i - max_len + 1

if max_len < ret_len[len(seq) - 1]:

max_len = ret_len[len(seq) - 1]

max_seq_start = len(seq) - max_len

return seq[max_seq_start:max_seq_start + max_len]

if __name__ == "__main__":

s = solution()

print s.max_up_seq([1,2,3,4])

print s.max_up_seq([1,2,3,4,2,3,3,4])

print s.max_up_seq([1,2,1,2,3,4,7,8,9,1,2,4,5,7])

這道題是動態規劃最經典的問題,網上求解方法很多。題目內容大致是, 有5個商品,揹包的體積為10,他們的體積為 c[5] = , 價值為 v[5] = ,如何利用揹包的體積放入價值最大的物品。乙個物品只能放入或者沒有放入揹包。

狀態方程如下。

v[i][j]=max(v[i-1][j],f[i-1][j-ci]+vi)

其中c是揹包體積,v[i][j]放入第i個物品總體積為j時的總價值,c[i]是第i個商品體積,v[i]是第i商品價值。**如下:

# include 

const

int max_num = 100;

int v[max_num][max_num];

int bag(int volum, int n, int* weight, int* value)

for (int i = 0; i < n + 1; ++i)

for (int i = 0; i < volum + 1; ++i)

printf("volum:%d num:%d\", volum, n);

for (int j = 1; j < volum+1; ++j) else

v[i][j] = max;

}printf("%d %d item:%d\", i, j, v[i][j]);}}

return 0;

}int main() ;

int value[6] = ;

bag(10, 5, weight, value);

printf("max value: %d\", v[5][10]);

return 0;

}

三道動態規劃題

三道簡單的動態規劃題 有 m x n 個格仔,機械人在最左上角的格仔,星星在最右下角的格仔。機械人只能向左和向下走。問 機械人拿到星星,總共有多少種拿法?如下圖 思路 問題其實就是從左上角走到右下角,有多少種走法。如果倒過來看,站在右下角的角度,走到右下角,只有2種可能 一是從右下角格仔的左邊走來 ...

刷題86 動態規劃(三)

題目鏈結題目描述 給定乙個非負整數 num。對於 0 i num 範圍中的每個數字 i 計算其二進位制數中的 1 的數目並將它們作為陣列返回。示例 1 輸入 2 輸出 0,1,1 示例 2 輸入 5 輸出 0,1,1,2,1,2 高階 題目分析 法一 動態規劃 找規律 奇數二進位制中1的個數比前乙個...

LeetCode刷題 動態規劃(三)

最長公共子串行問題,最基本的問題是在兩個字串中找出最長公共字串。方法是使用雙指標 i,j遍歷兩個字串,建立二維 dp 陣列,通過填表獲得結果。1143,最長公共子串行,medium 583,兩個字串的刪除操作,medium 712,兩個字串的最小ascii刪除和,medium 1143,最長公共子串...