動態規劃,又名DP算法(取自其Dynamic Programming的縮寫),最初是運籌學的一個分支,是用來求解決策過程最優化的數學方法。算法
把 多階段過程 轉化爲一系列單階段過程,利用各階段之間的關係,逐個求解。那什麼叫多階段過程呢?數組
多階段過程:首先你們能夠思考一下如下這個問題:
假如咱們有面值爲1元/3元/5元的硬幣若干枚,如何用最少的硬幣湊夠137元?
固然咱們可使用暴力枚舉解決這個問題,不夠那樣複雜度就過高了。咱們能夠這樣考慮,湊齊137元能夠當作一個最終目標,咱們能夠把它細分爲先以最少的硬幣數量湊齊136元(這樣再加1元就137元了)或是133元或是132元 + 1次。而後咱們的問題轉變爲了先以最少的硬幣數量湊齊136元或是133元或是132元。看似問題數量變動多了,可是實際問題難度卻變小了。
並且這種細分方式能夠不斷細分,一直細分到接近於0元。而在這個思惟過程當中,咱們就是將解決137元的問題分階段的完成,而這個過程就叫作 多階段過程 。框架
相對於其餘基本算法,動態規劃算法比較靈活,其主體框架取決於其具體問題,具體問題決定具體的狀態轉移方程;所以,其不像回溯法有一套「亙古不變」的算法框架;因此如下的算法只能說是解決相似上述硬幣問題的DP算法框架,只能算是給各位拋磚引玉。
變量解釋:
res:存儲各階段問題的答案
n:最終問題的標記位
i:循環的索引
f:某階段問題的答案與前些階段問題答案之間的函數關係函數
void dp(int n) { // 定義問題的解數組 int res[n + 1]; // 初始化最小的單階段問題的解 res[1] = 1 ... // 從初始化後的解數組的第一個位置開始循環計算res[i] int i = inital; while (i <= n) { // f函數取決於狀態轉移方程 res[i] = f(res[i - 1], res[i - 2], res[i - 3]...); i++; } return res[n]; }
經典問題:Best Time to Buy and Sell Stock
Say you have an array for which the ith element is the price of a given stock on day i.
If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.
Note that you cannot sell a stock before you buy one.
Example 1:
Input: [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
Not 7-1 = 6, as selling price needs to be larger than buying price.
Example 2:
Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.優化
int maxProfit(int* prices, int pricesSize) { if (pricesSize == 0) { return 0; } int res[pricesSize]; int min[pricesSize]; res[0] = 0; min[0] = prices[0]; int i = 1; while (i < pricesSize) { if (res[i - 1] < prices[i] - min[i - 1]) { res[i] = prices[i] - min[i - 1]; } else { res[i] = res[i - 1]; } if (prices[i] < min[i - 1]) { min[i] = prices[i]; } else { min[i] = min[i - 1]; } i++; } return res[pricesSize - 1]; }