Maximum Path Sum I
Let T be a triangular array of 15 rows. A path from the apex to the base selects one entry per row such that each successive entry is adjacent (directly below or below-right) to its predecessor. Fi...
Problem Statement
This archive keeps the full statement, math, and original media on the page.
By starting at the top of the triangle below and moving to adjacent numbers on the row below, the maximum total from top to bottom is \(23\). \[ \begin {tabular}{cccccccc} & & & 3 & & & & \\ & & 7 & & 4 & & & \\ & 2 & & 4 & & 6 & & \\ 8 & & 5 & & 9 & & 3 & \\ \end {tabular} \] That is, \(3 + 7 + 4 + 9 = 23\).
Find the maximum total from top to bottom of the triangle below:
75
95 64
17 47 82
18 35 87 10
20 04 82 47 65
19 01 23 75 03 34
88 02 77 73 07 63 67
99 65 04 28 06 16 70 92
41 41 26 56 83 40 80 70 33
41 48 72 33 47 32 37 16 94 29
53 71 44 65 25 43 91 52 97 51 14
70 11 33 28 77 73 17 78 39 68 17 57
91 71 52 38 17 14 91 43 58 50 27 29 48
63 66 04 68 89 53 67 30 73 16 69 87 40 31
04 62 98 27 23 09 70 98 73 93 38 53 60 04 23
Problem 18: Maximum Path Sum I
Mathematical Development
Definition 1. A triangular array of rows is a collection of entries for and . An adjacent path is a sequence with and for . The path sum is .
Definition 2. Define the optimal value function by
Theorem 1 (Bellman equation — optimal substructure). satisfies the recurrence
and the answer to the problem is .
Proof. We proceed by strong induction on .
Base case (): The only path from consists of the single entry , so .
Inductive step: Suppose the claim holds for all rows . Any path from to row must pass through either or as its next node. By the inductive hypothesis, the maximum path sum from onward is , and from onward is . Therefore:
Setting , gives the global optimum.
Theorem 2 (Greedy suboptimality). No greedy strategy that selects the locally larger child at each step is guaranteed to find the optimal path.
Proof. Counterexample: Let with , , . The greedy strategy chooses , while the optimal path is .
Theorem 3 (Space-optimal bottom-up evaluation). The recurrence in Theorem 1 can be evaluated bottom-up using a single array of length , overwriting entries in place.
Proof. Initialize for . For down to , update for . At the start of iteration , for . The update for index reads and (both still holding row- values, since we process left-to-right and only overwrite positions ) and writes to . Positions are not needed again for row . By induction, after the final iteration (), .
Proposition 1 (Path count). The number of distinct adjacent paths in an -row triangle is .
Proof. At each of the transitions between consecutive rows, there are exactly 2 choices (move to or ). The choices are independent, giving paths. For , this is .
Editorial
We solve the triangle with bottom-up dynamic programming. Starting from the last row, we traverse upward row by row and replace each entry by its value plus the larger of the two best totals directly beneath it. This is sufficient because any maximal path from a cell must continue through one of those two children, so the updated entry stores the best possible total from that position.
Pseudocode
Algorithm: Maximum Triangle Path Sum by Bottom-up Dynamic Programming
Require: A triangle of integers.
Ensure: The maximum total along a top-to-bottom path.
1: Let best be a working copy of the last row of the triangle.
2: For each higher row, processed from bottom to top, do:
3: Replace every entry by its value plus max(best_j, best_(j+1)) from the row immediately below.
4: Let best be the updated row.
5: Return the unique entry remaining at the top.
Complexity Analysis
Proposition 2 (Time complexity). The algorithm performs exactly additions and comparisons, giving time.
Proof. At iteration (for ), the inner loop executes iterations. The total is . Each iteration performs work. For : operations.
Proposition 3 (Space complexity). The algorithm uses auxiliary space for array , beyond the input storage.
Proof. has entries. No other data structure grows with .
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<vector<int>> tri = {
{75},
{95, 64},
{17, 47, 82},
{18, 35, 87, 10},
{20, 4, 82, 47, 65},
{19, 1, 23, 75, 3, 34},
{88, 2, 77, 73, 7, 63, 67},
{99, 65, 4, 28, 6, 16, 70, 92},
{41, 41, 26, 56, 83, 40, 80, 70, 33},
{41, 48, 72, 33, 47, 32, 37, 16, 94, 29},
{53, 71, 44, 65, 25, 43, 91, 52, 97, 51, 14},
{70, 11, 33, 28, 77, 73, 17, 78, 39, 68, 17, 57},
{91, 71, 52, 38, 17, 14, 91, 43, 58, 50, 27, 29, 48},
{63, 66, 4, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31},
{ 4, 62, 98, 27, 23, 9, 70, 98, 73, 93, 38, 53, 60, 4, 23}
};
int n = tri.size();
for (int r = n - 2; r >= 0; r--)
for (int c = 0; c <= r; c++)
tri[r][c] += max(tri[r + 1][c], tri[r + 1][c + 1]);
cout << tri[0][0] << endl;
return 0;
}
"""Project Euler Problem 18: Maximum Path Sum I"""
def main():
triangle = [
[75],
[95, 64],
[17, 47, 82],
[18, 35, 87, 10],
[20, 4, 82, 47, 65],
[19, 1, 23, 75, 3, 34],
[88, 2, 77, 73, 7, 63, 67],
[99, 65, 4, 28, 6, 16, 70, 92],
[41, 41, 26, 56, 83, 40, 80, 70, 33],
[41, 48, 72, 33, 47, 32, 37, 16, 94, 29],
[53, 71, 44, 65, 25, 43, 91, 52, 97, 51, 14],
[70, 11, 33, 28, 77, 73, 17, 78, 39, 68, 17, 57],
[91, 71, 52, 38, 17, 14, 91, 43, 58, 50, 27, 29, 48],
[63, 66, 4, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31],
[ 4, 62, 98, 27, 23, 9, 70, 98, 73, 93, 38, 53, 60, 4, 23],
]
n = len(triangle)
dp = triangle[-1][:]
for r in range(n - 2, -1, -1):
for c in range(r + 1):
dp[c] = triangle[r][c] + max(dp[c], dp[c + 1])
print(dp[0])