Grade 11 · Dynamic programmingCitește în română

Maximum sum in a number triangle

Original: Suma maximă în triunghiul de numere

O(n²)C++1766 lines1 example

The idea

A triangle has n rows; row i holds i numbers. We start from the top and at every step go either straight down (a[i+1][j]) or down and to the right (a[i+1][j+1]). We want the maximum sum of the numbers on the path. We work from the bottom up: s[i][j] = a[i][j] + max(s[i+1][j], s[i+1][j+1]), and on the last row s[n][j] = a[n][j]. The answer is s[1][1]. The path is rebuilt from the top down, always moving to the child with the larger s (straight down, on ties).

Original description (Romanian)

Un triunghi are n linii; linia i conține i numere. Pornim din vârf și la fiecare pas coborâm fie drept în jos (a[i+1][j]), fie în jos și la dreapta (a[i+1][j+1]). Vrem suma maximă a numerelor de pe drum. Lucrăm de jos în sus: s[i][j] = a[i][j] + max(s[i+1][j], s[i+1][j+1]), iar pe ultima linie s[n][j] = a[n][j]. Răspunsul este s[1][1]. Drumul se reface de sus în jos, mergând mereu spre fiul cu s mai mare (drept în jos, la egalitate).

Complexity
O(n²) time and memory
Grade
Grade 11 (Clasa a XI-a)

Examples

Example 1

Input

4
5
4 6
2 9 1
8 3 5 7

Expected output

25
5 6 9 5

The code

Comments are in Romanian, as in the original collection. Edit freely: you can reset at any time.

triunghiul-de-numere.cpp
/*
 * Titlu: Suma maximă în triunghiul de numere
 * Clasa: 11
 * Capitol: Programare dinamică
 * Descriere: Un triunghi are n linii; linia i conține i numere. Pornim din vârf și la
 *            fiecare pas coborâm fie drept în jos (a[i+1][j]), fie în jos și la dreapta
 *            (a[i+1][j+1]). Vrem suma maximă a numerelor de pe drum. Lucrăm de jos în sus:
 *            s[i][j] = a[i][j] + max(s[i+1][j], s[i+1][j+1]), iar pe ultima linie
 *            s[n][j] = a[n][j]. Răspunsul este s[1][1]. Drumul se reface de sus în jos,
 *            mergând mereu spre fiul cu s mai mare (drept în jos, la egalitate).
 * Complexitate: O(n²) timp și memorie
 *
 * Exemplu
 * Intrare:
 * 4
 * 5
 * 4 6
 * 2 9 1
 * 8 3 5 7
 * Ieșire:
 * 25
 * 5 6 9 5
 */
#include <iostream>
using namespace std;

int a[105][105], s[105][105];

int main()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= i; j++)
        {
            cin >> a[i][j];
        }
    }

    for (int j = 1; j <= n; j++)
    {
        s[n][j] = a[n][j];
    }
    for (int i = n - 1; i >= 1; i--)
    {
        for (int j = 1; j <= i; j++)
        {
            s[i][j] = a[i][j] + max(s[i + 1][j], s[i + 1][j + 1]);
        }
    }
    cout << s[1][1] << '\n';

    int j = 1;
    for (int i = 1; i <= n; i++)
    {
        cout << a[i][j] << ' ';
        if (i < n && s[i + 1][j + 1] > s[i + 1][j])
        {
            j++;
        }
    }
    cout << '\n';
    return 0;
}

Runs on a real g++ (C++17, -O2) through Compiler Explorer. Keep runs short; there's a time limit.