数字三角形-动态规划

116 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情

题目描述

图片描述

上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。 路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右 边的那个数。此外,向左下走的次数与向右下走的次数相差不能超过 1。

输入描述

输入的第一行包含一个整数 N (1≤N≤100),表示三角形的行数。

下面的 N 行给出数字三角形。数字三角形上的数都是 0 至 100 之间的整数。

输出描述

输出一个整数,表示答案。

输入输出样例

示例

输入

5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

输出

27

解题思路

首先我们先把问题拆分,先去寻找最大值,再说向左向右次数相差不超过1问题。我们要从上往下寻找最大值,如果我们只看第一行,那么最大值就是7;只看前两行,那么最大值就是(3+7=10,8+7=15)15;如果看前三行,最大值(8+上一行3的最大值10=18,1+Math.max(上一行3的最大值10,上一行8的最大值15)=1+15=16,0+上一行8的最大值15=15)16;以此类推就能找到最后一行以当前数为最后一个值的最大值。

image.png

那照这样看答案为什么不是最后最大的值30呢,原因是题目还要求左下走的次数与向右下走的次数相差不能超过 1。而从顶部的7走到30向左走了3次,向右只走了一次,所以不符合条件。而符合条件的只有最后一层的中位数,也就是27。

代码

import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int n = scan.nextInt();
		int[][] arr = new int[n + 1][n + 1];
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= i; j++) {
				arr[i][j] = Math.max(arr[i - 1][j - 1],arr[i - 1][j]) + scan.nextInt();
			}
		}
		System.out.println(n % 2 == 0 ? Math.max(arr[n][n / 2],arr[n][n / 2 + 1]) : arr[n][n / 2 + 1]);
		scan.close();
	}
}

image.png

总结

本题使用一个二维数组来保存每一步执行的最大值,也就是使用动态规划,还需要有一点点的思考想到向左向右移动差值不超过一就是寻找中位数。