题目描述

将正整数排成等边三角形(也叫数塔),三角形的底边有个数,下图给出了的一个例
子。从三角形顶点出发通过一系列相邻整数(在图中用正方形表示),如何使得到达底边
时的总和最大?

算法思想

动态规划
自顶向下应用递推式F[i][j] = num[i][j] + max(F[i+1][j], F[i+1][j+1])一级一级向下求解。

结果

代码

package CourseDesign;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

import java.util.Arrays;

public class B2 extends Application {
   
    long sleep = 0;

    @Override
    public void start(Stage primaryStage) throws Exception {
   
        // 初始化画布
        GridPane gridPane = new GridPane();
        gridPane.setMinSize(300, 200);
        gridPane.setAlignment(Pos.CENTER);
        gridPane.setPadding(new Insets(10));
        gridPane.setVgap(15);
        gridPane.setHgap(20);

        paintNumes(gridPane);

        // 建立线程开始计算
        Thread thread = new Thread(() -> {
   
            int[][] numes = getNumes();// 得到处理的数塔
            int max = getMax_V(gridPane, numes, 0, 0, true);// 返回计算结果
            Text text1 = new Text("最大值:" + max);// 输出到界面
            text1.setFont(Font.font(30));
            Runnable runnable = () -> {
   
                gridPane.add(text1, 2*numes.length - 1, 1 + numes.length);// 新建线程输出到界面
            };
            Platform.runLater(runnable);
        });
        thread.setDaemon(true);// 设置线程属性
        thread.start();

        primaryStage.setScene(new Scene(gridPane));
        primaryStage.show();
    }

    // 将原始数塔画出来
    private void paintNumes(GridPane gridPane) {
   
        int[][] numes = getNumes();
        int l = numes.length - 1;
        for (int i = 0; i < numes.length; i++) {
   
            int t = l--;
            for (int j = 0; j <= i; j++) {
   
                gridPane.add(getText(numes[i][j]), t, i);
                t += 2;
            }
        }
    }

    // 返回预定义的数组
    private int[][] getNumes() {
   
        int[][] numes = new int[5][5];
        int[] n = {
   9, 12, 15, 10, 6, 8, 2, 18, 9, 5, 19, 7, 10, 4, 16};
        int p = 0;
        for (int i = 0; i < 5; i++) {
   
            for (int j = 0; j <= i; j++) {
   
                numes[i][j] = n[p++];
            }
        }
        return numes;
    }
    // 测试用
    private static int[][] getNumes1() {
   
        int[][] numes = new int[5][5];
        int[] n = {
   9, 12, 15, 10, 6, 8, 2, 18, 9, 5, 19, 7, 10, 4, 16};
        int p = 0;
        for (int i = 0; i < 5; i++) {
   
            for (int j = 0; j <= i; j++) {
   
                numes[i][j] = n[p++];
            }
        }
        return numes;
    }

    // 返回一个带有指定数字k的Text标签
    private Text getText(int k) {
   
        Text text = new Text(Integer.toString(k));
        text.setFont(Font.font(30));
        text.setFill(Color.GREEN);
        return text;
    }



    /** * // 画图动态显示计算 * @param gridPane 面板 * @param nums 数塔 * @param row 行 * @param column 列 * @param biger 是否是较大值 * @return 从当前节点走到数塔底部的最大值 */
    public synchronized int getMax_V(GridPane gridPane, int[][] nums, int row, int column, boolean biger) {
   
        setColor(gridPane, nums, row, column, Color.RED);// 先画红色

        if (row == nums.length - 1) {
   // 到数塔底部
            if (!biger) {
   
                setColor(gridPane, nums, row, column, Color.GREEN);// 不是较大值用绿色
            }
            return nums[row][column];
        }

        int l = getMax(nums, row + 1, column);// 预处理左子树
        int r = getMax(nums, row + 1, column + 1);// 预处理右子树
        int max = nums[row][column] + Math.max(getMax_V(gridPane, nums, row + 1, column, l > r), getMax_V(gridPane, nums, row + 1, column + 1, r > l));
        if (!biger) {
   //不是最大值,画回绿色
            setColor(gridPane, nums, row, column, Color.GREEN);
        }

        return max;
    }

    // 通过节点位置给节点画指定颜色
    private void setColor(GridPane gridPane, int[][] nums, int row, int column, Color color) {
   
        try {
   
            sleep = 600;
            Thread.sleep(sleep);
        } catch (InterruptedException e) {
   
            e.printStackTrace();
        }
        Runnable runnable = () -> {
   
            Text text = getText(nums[row][column]);
            text.setFill(color);
            gridPane.add(text, (nums[0].length - 1) - row + column * 2, row);
        };
        Platform.runLater(runnable);
    }

    // 预处理函数得到指定节点到数塔底部的最大值
    public static int getMax(int[][] nums, int row, int column) {
   
        if (row == nums.length - 1)
            return nums[row][column];
        return nums[row][column] + Math.max(getMax(nums, row + 1, column), getMax(nums, row + 1, column + 1));
    }

    public static void main(String[] args) {
   
        launch(args);
// System.out.println(getMax(getNumes1(), 0, 0));
    }
}