关注微信公众号:怒码少年,回复关键词【电子书】可以免费获取计算机相关电子书
本文首发于:原文阅读-wx公众号:怒码少年
大家好,我是小码。
本篇是一道入门的最大路径和问题,使用的解决方法也是最简单,初学者请放心食用🍚。
数学三角形
题目描述
上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,请找到最大的和。
本题目来自蓝桥云课
路径上的每一步只可沿左斜线向下或右斜线向下走。
输入描述
输入的第一行包含一个整数N(1 <= N <= 100),表示三角形的行数。
接下来输入的N行都是组成数字三角形的数字,范围在0-99。
- 5
- 7
- 3 8
- 8 1 0
- 2 7 4 4
- 4 5 2 6 5
输出描述
从顶到底路径上最大的和。
30
思路分析
一般来说,这道题你看完题目之后,你的正常反应就是这个三角形好像一个树,那我就从树的根结点触发,每到一个结点都找这个结点中左右子结点中最大的那个不就好了吗?😏就像这样:
从第一层的7往下走,3和8的左右结点选最大的那个,所以走到8,8的左右子结点1和0选1,1的左右子结点7和4选7……就这样一直走到最后一层5。这样一条路径(7->8->1->7->5,暂且称为红色路径)就走完了,路径和是28,一切都是那么的完美。😁
但是我想说如果你这样做这道题,那你就大错特错啦~
注意看,如果我选择的是路径(7->3->8->7->5,暂且称为蓝色路径),路径和是30。
欸??不对啊,刚刚的红色路径每一次向下层走都是取得最大值,怎么你在第一步走的是3反而比走8的路径和还要大呢?🤔
根本原因:局部最优性不一定能推出全局最优性。
简单的来说,这道题求的是这个N行三角形中路径和的最大值,如果你是从顶层往底层走,你在第i层选择的最大子结点只能确定这个结点是这一层最大,但是你不能知道选择这个结点之后,这个结点本身和可以在后面的N-i层可以选择的路径和是不是最大的。
就拿刚刚的红色路径和蓝色路径比较,你在第2层选择的结点8是比第2层的结点3要大(局部最优性),但是结点8和之后可以选择的路径和(8->1->7->5)比结点3和之后可以选择的路径和(3->8->7->5)要小(推不出全局最优性)。
那可怎么办?每选择一步都会影响到后面的所有呀,又不能知道后面结点的情况。😭
这个时候,我们应该想想有没有一种办法可以不影响?🤔
答案是自底向上查找路径。
假设在这个例子中你已经走到N-1层的某一结点了,无论你前面的N-2层是怎么走的,接下来你一定会选择这个结点的左右结点中的最大值作为最后一步,使得你的路径和是最大的,如:
那么第N-1层应该选哪个结点呢?这是由第N-2层决定的,第N-2层决定的时候肯定要选择选择的结点可以使最后两层的和是最大的,因此我们可以在N-1层做决定的时候把最后两层的和求出供第N-2层选择,如图:
接下来的也是同理:
……
就这样一直到最后在加上根结点7就是最后的答案30。相当于自底向上选择路径:
代码实现
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
//输入行数
int n = scan.nextInt();
int [][]a = new int[101][101];
//输入数字三角形
for(int i = 0 ; i < n;i++){
for(int j = 0 ; j <= i; j++ ){
a[i][j] = scan.nextInt();
}
}
//从第n-1层开始比较子结点的大小
for(int i = n-2; i >= 0 ; i--){
for(int j = 0 ; j <= i ; j++){
//选择子结点中交到的那个加当前层中
if(a[i+1][j] >= a[i+1][j+1]){
a[i][j]+=a[i+1][j];
}else{
a[i][j]+=a[i+1][j+1];
}
}
}
System.out.println(a[0][0]);
scan.close();
}
}
END
看到标题感觉有种很亲切的感觉,上次更【算法通关】系列是在两个月前了,这一次我要拿回属于我的一切💪(bushi
关注微信公众号:怒码少年,回复关键词【电子书】可以免费获取计算机相关电子书