動態規劃的概念對於新手來講枯燥難懂,就算看懂了,作題的時候依舊抓耳撓腮的毫無頭緒,這些比較難理解的算法,仍是須要根據例子來一步步學習和理解,從而熟練掌握,下面,我們就經過一個簡單的小例子來學習動態規劃:java
數字三角形(POJ1163)算法
在上面的數字三角形中尋找一條從頂部到底邊的路徑,使得路徑上所通過的數字之和最大。數組
路徑上的每一步都只能往左下或 右下走。只須要求出這個最大和便可,沒必要給出具體路徑。 三角形的行數大於1小於等於100,數字爲 0 - 99網絡
輸入格式:函數
5 //表示三角形的行數 接下來輸入三角形學習
7優化
3 8spa
8 1 03d
2 7 4 4code
4 5 2 6 5
要求輸出最大和
我們來分析這道題:
1.須要有一個變量 n 來存儲輸入的行數
2.須要一個二維數組 a 來存儲輸入的數字三角形
3.須要另外一個一樣大小的二維數組 b,用來存儲到每一層的每個數的最短路徑,
例如:
到三角形的第三層,有兩條路會通過1,
因爲7+3=10<7+8=15,因此b數組的1的位置存儲的是最短路徑7—>3—>1等於11,
而在最兩邊的,就直接累加就ok了,7+3+8=18,7+8+0=15
這也是這個程序的核心部分,代碼以下:
由於第一層跟a數組的第一層相同,因此i從1開始循環
而後遍歷最後一層,求出最小值就ok啦
b數組最後的值
完整代碼以下:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sca = new Scanner(System.in); int n = sca.nextInt(); int[][] a = new int[n][n]; int[][] b = new int[n][n]; int min; for(int i = 0;i<n;i++){ for(int j = 0;j<=i;j++){ a[i][j] = sca.nextInt(); } } b[0][0] = a[0][0]; for(int i = 1;i<n;i++){ for(int j = 0;j<=i;j++){ if(j==0)//左側,直接相加 b[i][j] = b[i-1][j]+a[i][j]; else if(j==i)//右側,直接相加 b[i][j] = b[i-1][j-1]+a[i][j]; else//中間,須要用min函數求通過這條路的最短路徑 b[i][j] = Math.min(b[i-1][j-1],b[i-1][j])+a[i][j]; } } min = b[n-1][0]; for(int i = 1;i<b[n-1].length;i++){ if(b[n-1][i]<min) min = b[n-1][i]; } System.out.println(min); } }
總結一下動態規劃的解題思路:
1,將原問題分解爲簡單的子問題,子問題求出來以後,原問題也就很容易獲得了
2,肯定狀態轉移方程
這道題的狀態轉移方程: