All Euler problems
Project Euler

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...

Source sync Apr 19, 2026
Problem #0018
Level Level 00
Solved By 158,398
Languages C++, Python
Answer 1074
Length 447 words
dynamic_programminggeometrygreedy

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

Note: As there are only \(16384\) routes, it is possible to solve this problem by trying every route. However, , is the same challenge with a triangle containing one-hundred rows; it cannot be solved by brute force, and requires a clever method! ;o)

Problem 18: Maximum Path Sum I

Mathematical Development

Definition 1. A triangular array TT of nn rows is a collection of entries T[r][c]T[r][c] for 0rn10 \le r \le n-1 and 0cr0 \le c \le r. An adjacent path is a sequence (c0,c1,,cn1)(c_0, c_1, \ldots, c_{n-1}) with c0=0c_0 = 0 and cr+1{cr,cr+1}c_{r+1} \in \{c_r, c_r + 1\} for 0r<n10 \le r < n - 1. The path sum is r=0n1T[r][cr]\sum_{r=0}^{n-1} T[r][c_r].

Definition 2. Define the optimal value function M:{0,,n1}×N0ZM : \{0, \ldots, n-1\} \times \mathbb{N}_0 \to \mathbb{Z} by

M[r][c]=max ⁣{i=rn1T[i][ci]  |  cr=c,  ci+1{ci,ci+1} for ri<n1}.M[r][c] = \max\!\left\{\sum_{i=r}^{n-1} T[i][c_i] \;\middle|\; c_r = c,\; c_{i+1} \in \{c_i, c_i + 1\} \text{ for } r \le i < n-1\right\}.

Theorem 1 (Bellman equation — optimal substructure). MM satisfies the recurrence

M[r][c]={T[n1][c]if r=n1,T[r][c]+max(M[r+1][c],  M[r+1][c+1])if 0r<n1,M[r][c] = \begin{cases} T[n-1][c] & \text{if } r = n - 1, \\ T[r][c] + \max\bigl(M[r+1][c],\; M[r+1][c+1]\bigr) & \text{if } 0 \le r < n - 1, \end{cases}

and the answer to the problem is M[0][0]M[0][0].

Proof. We proceed by strong induction on n1rn - 1 - r.

Base case (r=n1r = n - 1): The only path from (n1,c)(n-1, c) consists of the single entry T[n1][c]T[n-1][c], so M[n1][c]=T[n1][c]M[n-1][c] = T[n-1][c].

Inductive step: Suppose the claim holds for all rows r>rr' > r. Any path from (r,c)(r, c) to row n1n - 1 must pass through either (r+1,c)(r+1, c) or (r+1,c+1)(r+1, c+1) as its next node. By the inductive hypothesis, the maximum path sum from (r+1,c)(r+1, c) onward is M[r+1][c]M[r+1][c], and from (r+1,c+1)(r+1, c+1) onward is M[r+1][c+1]M[r+1][c+1]. Therefore:

M[r][c]=T[r][c]+max(M[r+1][c],  M[r+1][c+1]).M[r][c] = T[r][c] + \max\bigl(M[r+1][c],\; M[r+1][c+1]\bigr).

Setting r=0r = 0, c=0c = 0 gives the global optimum. \square

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 n=3n = 3 with T[0][0]=1T[0][0] = 1, T[1]=[2,3]T[1] = [2, 3], T[2]=[100,0,0]T[2] = [100, 0, 0]. The greedy strategy chooses 130=41 \to 3 \to 0 = 4, while the optimal path is 12100=1031 \to 2 \to 100 = 103. \square

Theorem 3 (Space-optimal bottom-up evaluation). The recurrence in Theorem 1 can be evaluated bottom-up using a single array AA of length nn, overwriting entries in place.

Proof. Initialize A[c]T[n1][c]A[c] \gets T[n-1][c] for 0cn10 \le c \le n - 1. For r=n2r = n - 2 down to 00, update A[c]T[r][c]+max(A[c],A[c+1])A[c] \gets T[r][c] + \max(A[c], A[c+1]) for c=0,1,,rc = 0, 1, \ldots, r. At the start of iteration rr, A[c]=M[r+1][c]A[c] = M[r+1][c] for 0cr+10 \le c \le r + 1. The update for index cc reads A[c]A[c] and A[c+1]A[c+1] (both still holding row-(r+1)(r+1) values, since we process left-to-right and only overwrite positions c\le c) and writes M[r][c]M[r][c] to A[c]A[c]. Positions c>rc > r are not needed again for row rr. By induction, after the final iteration (r=0r = 0), A[0]=M[0][0]A[0] = M[0][0]. \square

Proposition 1 (Path count). The number of distinct adjacent paths in an nn-row triangle is 2n12^{n-1}.

Proof. At each of the n1n - 1 transitions between consecutive rows, there are exactly 2 choices (move to cc or c+1c + 1). The choices are independent, giving 2n12^{n-1} paths. For n=15n = 15, this is 214=163842^{14} = 16384. \square

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 r=0n2(r+1)=n(n1)2\sum_{r=0}^{n-2}(r+1) = \frac{n(n-1)}{2} additions and comparisons, giving Θ(n2)\Theta(n^2) time.

Proof. At iteration rr (for r=n2,n3,,0r = n - 2, n - 3, \ldots, 0), the inner loop executes r+1r + 1 iterations. The total is r=0n2(r+1)=j=1n1j=(n1)n2\sum_{r=0}^{n-2}(r+1) = \sum_{j=1}^{n-1} j = \frac{(n-1)n}{2}. Each iteration performs O(1)O(1) work. For n=15n = 15: 14152=105\frac{14 \cdot 15}{2} = 105 operations. \square

Proposition 3 (Space complexity). The algorithm uses Θ(n)\Theta(n) auxiliary space for array AA, beyond the Θ(n2)\Theta(n^2) input storage.

Proof. AA has nn entries. No other data structure grows with nn. \square

Answer

1074\boxed{1074}

Code

Each problem page includes the exact C++ and Python source files from the local archive.

C++ project_euler/problem_018/solution.cpp
#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;
}