1. 程式人生 > >JAVA程式碼—演算法基礎:數塔問題(動態規劃)

JAVA程式碼—演算法基礎:數塔問題(動態規劃)

數塔問題(使用動態規劃思路求解)

如圖所示,給定一個正整數構成的三角形,如下所示:
在下面的數字三角形中尋找一條從頂部到底邊的路徑,
使得路徑上所經過的數字之和最大。
路徑上的每一步都只能往左下或者右下走。
只需要求出這個最大和即可,不必給出路徑。
三角形的行數大於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); } }

(完)