這裏是簡單的動態規劃問題。其實,若是咱們學過數據結構,應該就接觸過動態規劃問題,當時一直沒有反應過來。咱們求最小生成樹用的是貪婪算法。而求最短路徑就是動態規劃。從一個點出發,到另外每一個點的最短距離。在求最短路徑問題中,取一點,而後與選取與這個點鏈接的,最小的一條邊,把這個點標上,而後求與標上點的鏈接的點的最短路徑。咱們先來看這道題目吧java
1.題目描述算法
將一個由N行數字組成的三角形,如圖因此,設計一個算法,計算出三角形的由頂至底的一條路徑,使該路徑通過的數字總和最小。數組
咱們能夠把這個橫過來看變成數據結構
7spa
3 4設計
8 5 0code
2 7 4 4blog
4 5 2 6 5遞歸
從頂部到底部,只能從7走到3,或者8,而後從3走到8和1,8走到1和0 。。。。ip
咱們本身計算最小路徑怎麼算呢。假如從7出發,咱們選擇與他們兩個的最長的一個,這是貪婪法,可是貪婪法有些時候不適用,好比這個圖,7的話,貪婪選最小的選3,可是最短路徑不是這條。
這道題目就要用到動態規劃,我從底到頂部,依次求出從底部到上一層的最短路求出來。每次求最短路徑,再記錄下來就行。這道題目簡單的地方就是上層的點到下層的路只有兩條。
也就是說共有5層,用一個tem[][]來存放從底層到這個點的最短路徑,那麼第5層從底到本身最短路徑仍是自己,4,5,2,6,5。第四層的就是temp[4][j] = temp[4][j] + Min{temp[5][j],temp[5][j+1]},只有這兩條路與上一層直接相連,就能直接標上。同理遞歸調用。。。
2.輸入描述
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
3.輸出描述:
輸出每一個點的從底部到這一點的最短路徑,都記錄下來。
17
10 14
14 7 6
6 9 6 9
4 5 2 6 5
4.代碼示例:
package a; import java.util.Scanner; public class DP { static int qipan[][] = new int[5][5]; static int temp[][] = new int[5][5]; //用來存放的最短路徑的 public static void main(String[] args) { Scanner scn = new Scanner(System.in); for(int i=0;i<5;i++) { for(int j=0;j<=i;j++) { qipan[i][j] = scn.nextInt(); temp[i][j] = qipan[i][j]; } } dp(qipan,4);//把棋盤的第5層開始求。第5層最短路是自己,數組下標是4 //輸出棋盤 for(int i=0;i<5;i++) { for(int j=0;j<=i;j++) { System.out.printf("%-4d",temp[i][j]); } System.out.println(); } //輸出路徑,這部分代碼只是用來輸出路徑的,調用print路徑 temp[0][0] = -1; print(temp,0); for(int i=0;i<5;i++) { for(int j=0;j<=i;j++) { if(temp[i][j] ==-1) { System.out.printf("%-4d",qipan[i][j]); }else { System.out.printf("%-4d",0); } } System.out.println(); } } private static void print(int[][] temp, int k) { if( k==4 ) { return; } for(int i=0;i<=k;i++) { if(temp[k][i]==-1) { if(temp[k+1][i]<temp[k+1][i+1]) { temp[k+1][i] = -1; }else { temp[k+1][i+1] = -1; } } } print(temp, k+1); } private static void dp(int[][] qipan, int k) { if(k ==0) { return; } for(int j=0;j<k;j++) { temp[k-1][j] = temp[k-1][j] + Math.min(temp[k][j], temp[k][j+1]); } dp(qipan, k-1); } }