JAVA程式碼—演算法基礎:數塔問題(動態規劃)
阿新 • • 發佈:2019-02-07
數塔問題(使用動態規劃思路求解)
如圖所示,給定一個正整數構成的三角形,如下所示:
在下面的數字三角形中尋找一條從頂部到底邊的路徑,
使得路徑上所經過的數字之和最大。
路徑上的每一步都只能往左下或者右下走。
只需要求出這個最大和即可,不必給出路徑。
三角形的行數大於1小於等於100,整數為0~99
輸入樣例:
輸入樣例:
5 – 三角形的行數
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
輸出結果為:
30
package com.bean.algorithmexec;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class ShuTa {
/*
* 數塔問題
* 給定一個正整數構成的三角形,如下所示:
* 7
* 3 8
* 8 1 0
* 2 7 4 4
* 4 5 2 6 5
* 在上面的數字三角形中尋找一條從頂部到底邊的路徑,
* 使得路徑上所經過的數字之和最大。
* 路徑上的每一步都只能往左下或者右下走。
* 只需要求出這個最大和即可,不必給出路徑。
* 三角形的行數大於1小於等於100,整數為0~99
*
* 輸入樣例:
* 5 -- 三角形的行數
* 7
* 3 8
* 8 1 0
* 2 7 4 4
* 4 5 2 6 5
*
* */
/*
* 思路分析:
* 使用二維陣列來存放數字三角形
* 然後使用D(x,y)來表示第x行第y個數字(x,y從1開始算)
* 使用MaxSum(x,y)表示從D(x,y)到底邊的各條路徑中,最佳路徑的數字和。
* 因此,此問題就轉換為求MaxSum(1,1)
* 這時,首先想到的就是可以使用簡單的遞迴思想來求解
* D(x,y)出發,下一步只能走D(x+1,y)或者D(x+1,y+1)。所以,對於N行的三角形,
* 可以寫出下面的遞迴算式:
* if(x==N)
* MaxSum(x,y)=D(x,y)
* else
* MaxSum(x,y)=Max(MaxSum(x+1,y),MaxSum(x+1,y+1))+D(x,y)
* 但是,這個演算法存在重複計算的問題,而且效率不好。
*
* 使用動態規劃解決的思路。
* 1、確定一個狀態:把當前位置(x,y)看成一個狀態,然後定義狀態(x,y)的指標函式d(x,y)為
* 從(x,y)出發時能夠得到的最大和(包括位置(x,y)本身的值)。在這個狀態定義下,原問題的
* 解是d(1,1)
* 2、確定狀態轉移方程
* 從位置(x,y)出發有兩種策略。如果往下走,則走到(x+1,y)後需求“從(x+1,y)出發後能得到的最大和”這一問題,
* 即d(x+1,y)。
* 如果往右下走,則走到(x+1,y+1)後需求“從(x+1,y+1)出發後能得到的最大和”這一問題,即d(x+1,y+1)
* 由於可以在這兩個決策中自由選擇,所以應選擇d(x+1,y)和d(x+1,y+1)中較大的一個。
* 所以,所謂的狀態轉移方程為:
* d(x,y)= a(x,y)+max(d(x+1,y),d(x+1,y+1))
*
* 動態規劃的核心是確立狀態轉移方程。
* */
public static void main(String[] args) throws FileNotFoundException {
// TODO Auto-generated method stub
System.setIn(new FileInputStream("G:\\shuta.txt"));
Scanner in = new Scanner(System.in);
int n = in.nextInt();
long max = 0;
int[][] dp = new int[n][n];
dp[0][0] = in.nextInt();
for (int i = 1; i < n; i++) {
for (int j = 0; j <= i; j++) {
int num = in.nextInt();
if (j == 0)
dp[i][j] = dp[i - 1][j] + num;
else
dp[i][j] = Math.max(dp[i - 1][j - 1], dp[i - 1][j]) + num;
max = Math.max(dp[i][j], max);
}
}
System.out.println(max);
}
}
(完)