動態規劃是演算法導論中介紹的最重要的幾種基本演算法之一,因為好長時間沒有看書,再加上原來就理解的不深入,所以早就忘的差不多了,這兩天正好因為一道面試題複習一下。
用幾句話描述動態規劃問題如下:
乙個問題可以分解若干子問題,每乙個子問題為一種狀態,求出每乙個狀態的最優解,進而在它的幫助下求出下乙個狀態的最優解。
解決動態規劃問題,最重要的步驟就是找出狀態轉移方程。有了狀態轉移方程就可以根據初始狀態(邊界)求出每乙個狀態的最優解。
動歸問題的特點如下:
下面用三道題目幫組理解一下。
有1分,3分,5分3種硬幣,如何使用最少的硬幣數量得到12分。這個題目的狀態轉移方程如下。
d(i) = min(d(i-v(j)) + 1)
其中d是硬幣數量,i是money總數,v(j)是第j個硬幣的單位。初始值d(0)=0。**如下:
題目的意思就是從乙個數列當中找出最長的公升序的子數列,比如」123412345123」的最長公升序子數列是」12345」,這個題目的狀態轉移方程如下。#! /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
"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)
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。**如下:
這道題是動態規劃最經典的問題,網上求解方法很多。題目內容大致是, 有5個商品,揹包的體積為10,他們的體積為 c[5] = , 價值為 v[5] = ,如何利用揹包的體積放入價值最大的物品。乙個物品只能放入或者沒有放入揹包。#! /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])
狀態方程如下。
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,最長公共子串...