Clasa a XI-a · Programare dinamicăRead in English

Suma maximă în triunghiul de numere în C++

În engleză: Maximum sum in a number triangle

O(n²)C++1766 de linii1 exemplu

Ideea

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

Descrierea în engleză

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

Complexitate
O(n²) timp și memorie
Clasa
Clasa a XI-a (Grade 11)

Exemple

Exemplul 1

Intrare

4
5
4 6
2 9 1
8 3 5 7

Ieșire așteptată

25
5 6 9 5

Codul C++

Codul complet, cu comentarii în română. Îl poți modifica liber și îl poți reseta oricând.

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;
}

Rulează pe un g++ adevărat (C++17, -O2) prin Compiler Explorer. Programele trebuie să se termine repede: există o limită de timp.