题目描述
上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。
路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右 边的那个数。此外,向左下走的次数与向右下走的次数相差不能超过 1。
输入描述
输入的第一行包含一个整数 n (1≤n≤100) (1≤n≤100),表示三角形的行数。
下面的 n 行给出数字三角形。数字三角形上的数都是 0 至 100 之间的整数。
输出描述
输出一个整数,表示答案。
输入输出样例
示例输入
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
示例输出
27
运行限制
- 最大运行时间:1s
- 最大运行内存: 256M
题目链接:数字三角形
-------------------------------------------
AC解题思路
1、这道题我的做法的是用动态规划二维数组进行解决,首先要理解动态规划这个概念,关于动态规划可以参考下列学习链接,讲得非常详细:
学习链接:动态规划学习链接
2、思路其实很简单,首先是分析题目的要求,我们可以使用一个整型二维数组array[][]对数组进行输入存储,然后通过二维数组dp[][]计算最大距离。
3、因为是从0开始进行计数,所以我们的题目需要的终点数据坐标就是n-1,m-1(n是行数,m是列数)
4、然后因为题目要求是只能从三角形的两边往上走,所以大致图解是这样
所以通过图解可以很清晰地得出一个表达式,即
dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j-1]) + array[i][j]
//dp数组是距离数组,array数组是数据格
5、最后便是对得出数据的判断,这里非常重要。
通过对dp数组(可以画一下)的分布数据可以总结出一个规律:
奇数行得出的最大值位于坐标(n-1,n/2)
偶数行得出的最大值位于坐标(n-1,n/2)和(n-1,n/2 -1)中的最大值
这个其实是利用了中位数的概念
思路大体就这些了,接下来请看代码
import java.util.Scanner;
import java.math.*;
//数字三角形(动态规划初学)
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int array[][] = new int[n][n];
for(int i=0;i<n;i++){
for(int j=0;j<=i;j++){
array[i][j] = scan.nextInt();
}
}//录入数组
int dp[][] = new int[n][n];
int m = n;
dp[0][0] = array[0][0];
for(int i=1;i<n;i++){
dp[i][0] = dp[i-1][0] + array[i][0];
}//三角形只需要初始化一边即可
for(int i=1;i<n;i++){
for(int j=1;j<=i;j++){
dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j-1])+array[i][j];
}
}//计算最大值
if(n%2!=0) {
System.out.println(dp[n-1][n/2]);
}else {
System.out.println(Math.max(dp[n-1][n/2], dp[n-1][n/2-1]));
}//进行距离判断
}
}