Tim Varley Logo
Tim Varley Principal AI Engineer and Tech Leader
Problem #18 medium

Maximum Path Sum I

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.

3 7 4 2 4 6 8 5 9 3

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 by trying every route. However, Problem 67, is the same challenge with a triangle containing one-hundred rows; it cannot be solved by brute force, and requires a clever method! ;o)

View on Project Euler

Implementations

cpp
// Answer: 1074
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
static const char* test_data_fname = "./src/euler_18_test_data.txt";
static const char* data_fname = "./src/euler_18_data.txt";
int maximum_path_sum_1(const char* fname)
{
std::ifstream fin(fname);
if( !fin.is_open()){
std::cerr << "Failed to open input file: " << fname << std::endl;
return -1;
}
std::vector<std::vector<int> > lines;
for( std::string line ; std::getline(fin,line);){
std::stringstream ss(line);
std::string number;
std::vector<int> inner;
while (std::getline(ss,number,',')) {
inner.push_back(std::stoi(number));
}
lines.push_back(inner);
}
for( int i = lines.size()-1; i > 0 ; --i){
for( int j = 0 ; j < i; j++){
if( lines[i][j] > lines[i][j+1] ){
lines[i-1][j] += lines[i][j];
}else{
lines[i-1][j] += lines[i][j+1];
}
}
}
return lines[0][0];
}
#if ! defined UNITTEST_MODE
int main(int argc, char const *argv[])
{
std::cout << "Answer: " << maximum_path_sum_1(data_fname) << std::endl;
}
#endif // #if ! defined UNITTEST_MODE
View on GitHub
O(n) time complexity

Solution Notes

Mathematical Background

This is a classic dynamic programming problem on a triangular grid. Each number can only move to one of two adjacent numbers in the row below. The goal is to find the path from top to bottom that maximizes the sum.

The triangle has 15 rows, with the bottom row having 15 elements. The total number of possible paths is 214=163842^{14} = 16384, which explains why brute force is feasible for this size.

Algorithm Analysis

All implementations use dynamic programming with O(n²) time complexity, where n is the number of rows. The algorithm starts from the bottom row and works upwards, replacing each number with the maximum sum achievable from that position.

Key steps:

  1. Start from the second-to-last row
  2. For each position, add the maximum of the two possible paths below
  3. Work upwards until reaching the top

This approach transforms the triangle in-place, using each row to store the maximum path sum to that point.

Key Insights

  • Dynamic programming eliminates the need to explore all paths
  • Working from bottom to top avoids recomputation
  • The optimal substructure property allows us to solve smaller subproblems first
  • This same approach scales to Problem 67’s much larger triangle
  • Memory usage remains O(n²) for the triangle storage

Educational Value

This problem introduces:

  • Dynamic programming concepts and optimal substructure
  • The difference between brute force and optimized algorithms
  • How exponential complexity can be reduced to polynomial
  • Tree/graph traversal techniques
  • The importance of choosing the right algorithmic approach based on problem size