试题 历届试题 数字三角形
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。
路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右边的那个数。此外,向左下走的次数与向右下走的次数相差不能超过 1。
输入格式
输入的第一行包含一个整数 ,表示三角形的行数。下面的 行给出数字三角形。数字三角形上的数都是 至 之间的整数。
输出格式
输出一个整数,表示答案。
样例输入
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
样例输出
27
首先题目有要求从上到下累加求最大值,所以我们容易想出用dp解决这个问题。但是题目还有一个限制条件 【向左下走的次数与向右下走的次数相差不能超过 1】。
通过观察我们可以发现在这个条件的限制下,我们从第一层出发到最后一层的 垂直距离差不能超过1(可以把空格也看成一个距离)于是就能得到这个规律
当行数 N为 :
奇数: 最后一定是走到了 [N-1] [N/2+1 ] 的位置
偶数: 最后一定是走到了 [N-1] [N/2 ] 或 [N-1] [N/2+1] 的位置
这样一来就解决了这个条件带来的问题
本文主要介绍如何化解这个条件带来的不便,该题的dp写法可以参考其他文章。
下面给出代码实现
public class Main{
public static void main(String[] args) {
SolutionSJX solutionSJX = new SolutionSJX();
solutionSJX.solve();
}
}
class SolutionSJX{
int dep[][] = new int[101][101] ;
int arr[][] = new int[101][101] ;
int N;
public void init(){
Scanner scanner = new Scanner(System.in);
N = scanner.nextInt();
for(int i =0;i<N;i++){
for(int j=0;j<=i;j++){
arr[i][j] = scanner.nextInt();
}
}
// 把dep[0] 作为填充位,减少判断
// dp[x][y] 表示 累加走到arr[x][y-1]时可以取到的最大值
// 要 -1 是因为有占位
dep[0][1]= dep[0][2] = arr[0][0];
}
public int dp(){
int max =0;
for(int row = 1;row <N;row++){
for(int col = 0;col<=row;col++) {
// 当前值 + max(左上,上)
dep[row][col+1] = Math.max(dep[row-1][col], dep[row-1][col+1])+arr[row][col];
}
}
// 确地合理路径的最终点
if(N%2 ==1){
//最中心点
max = dep[N-1][N/2+1];
}else{
//中心点的左右
max = Math.max(dep[N-1][N/2],dep[N-1][N/2+1]);
}
return max;
}
public void solve(){
init();
System.out.println(dp());
}
}