image.png
前言
????動態規劃不管是在筆試還是面試還是日常開發中也是比較常見的一種算法。今天主要簡單的介紹一些動態規劃的一些知識。
都是一些日常的積累,有問題可以指出來哦
基本概念
????動態規劃(dynamic programming)是運籌學的一個分支,是求解決策過程(decision process)最優化的數學方法。20世紀50年代初美國數學家R.E.Bellman等人在研究多階段決策過程(multistep decision process)的優化問題時,提出了著名的最優化原理(principle of optimality),把多階段過程轉化為一系列單階段問題,利用各階段之間的關系,逐個求解,創立了解決這類過程優化問題的新方法——動態規劃。
思想
????動態規劃算法的基本思想與分治法類似,也是將待求解的問題分解為若干個子問題(階段),按順序求解子階段,前一子問題的解,為后一子問題的求解提供了有用的信息。在求解任一子問題時,列出各種可能的局部解,通過決策保留那些有可能達到最優的局部解,丟棄其他局部解。依次解決各子問題,最后一個子問題就是初始問題的解。
使用條件
- 最優化原理:如果問題的最優解所包含的子問題的解也是最優的,就稱該問題具有最優子結構,即滿足最優化原理。
- 無后效性:即某階段狀態一旦確定,就不受這個狀態以后決策的影響。也就是說,某狀態以后的過程不會影響以前的狀態,只與當前狀態有關。
- 有重疊子問題:即子問題之間是不獨立的,一個子問題在下一階段決策中可能被多次使用到。(該性質并不是動態規劃適用的必要條件,但是如果沒有這條性質,動態規劃算法同其他算法相比就不具備優勢)
求解過程
- 將原問題分解為子問題
把原來的問題分解為若干的子問題,子問題和原問題是相似的,可能就是規模變小了。- 確定狀態
子問題相關的一組值,將作為狀態,實際上狀態就是子問題的解。- 確定初始狀態和邊界值
- 確定狀態轉移方程
根據已知的狀態得到未知的后序狀態,得到一組遞推方程,就是狀態轉移方程。
舉個例子
求最大連續子序列和問題。
給定一個數組[1 ,-5 ,2 ,4, -1, -5 ];
求連續子序列和最大。
1、 分解問題
上述為6個數的數組求解最大連續子序列和,轉化為將某個數作為子序列末尾求子序列最大和問題。
2、 確定狀態
數組中i作為子序列尾部時最大的和作為狀態。
3、 確定初始狀態和邊界
初始狀態均為數組值
4、 狀態轉移方程
數組第i個作為子序列尾部,第i-1個子序列位數的狀態為a,如果i加上a的狀態大于i本身的狀態,i的狀態需要加上i-1的狀態,反之狀態不變。
得到狀態方程:
dp[i]=max{dp[i-1]+array[i],array[i]};
代碼
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
int n=input.nextInt();
int []array=new int[n];
for (int i = 0; i <n ; i++) {
array[i]=input.nextInt();
}
int []dp=new int[n];
dp[0]=array[0];
for (int i = 1; i <n ; i++) {
dp[i]=Math.max(array[i],dp[i-1]+array[i]);
}
int max = Integer.MIN_VALUE;
for (int i = 0; i < n; i++) {
if (max < dp[i]) {
max = dp[i];
}
}
System.out.println(max);
}