Cod sursa(job #3346683)

Utilizator marius.popa1408Popa Marius marius.popa1408 Data 14 martie 2026 23:18:51
Problema Parantezare optima de matrici Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.97 kb
/*
A1 A2 A3 .... A5




*/

#include <limits>
#include <vector>

using namespace std;

// INF este valoarea maximă - "infinitul" nostru
const auto INF = std::numeric_limits<unsigned long long>::max();

// T = O(n ^ 3)
// S = O(n ^ 2) - stocăm n x n întregi în tabloul dp
unsigned long long main(int n, const vector<int> &d)
{
    // dp[i][j] = numărul MINIM înmulțiri scalare cu codare, poate fi calculat produsul
    //            matriceal M_i * M_i+1 * ... * M_j
    vector<vector<unsigned long long>> dp(n + 1, vector<unsigned long long>(n + 1, INF));

    // Cazul de bază 1: nu am ce înmulți
    for (int i = 1; i <= n; ++i)
    {
        dp[i][i] = 0ULL; // 0 pe unsigned long long (voi folosi mai încolo și 1ULL)
    }

    // Cazul de bază 2: matrice d[i - 1] x d[i] înmulțită cu matrice d[i] x d[i + 1]
    // (matrice pe poziții consecutive)
    for (int i = 1; i < n; ++i)
    {
        dp[i][i + 1] = 1ULL * d[i - 1] * d[i] * d[i + 1];
    }

    // Cazul general:
    // dp[i][j] = min(dp[i][k] + dp[k + 1][j] + d[i - 1] * d[k] * d[j]), k = i : j - 1
    for (int len = 2; len <= n; ++len)
    { // fixăm lungimea intervalului (2, 3, 4, ...)
        for (int i = 1; i + len - 1 <= n; ++i)
        {                        // fixăm capătul din stânga: i
            int j = i + len - 1; // capătul din dreapta se deduce: j

            // Iterăm prin indicii dintre capete, spărgând șirul de înmulțiri in două (paranteze).
            for (int k = i; k < j; ++k)
            {
                // M_i * ... M_j  = (M_i * .. * M_k) * (M_k+1 *... * M_j)
                unsigned long long new_sol = dp[i][k] + dp[k + 1][j] + 1ULL * d[i - 1] * d[k] * d[j];

                // actualizăm soluția dacă este mai bună
                dp[i][j] = min(dp[i][j], new_sol);
            }
        }
    }

    // Rezultatul se află în dp[1][n]: Numărul MINIM de inmultiri scalare
    // pe care trebuie să le facem pentru a obține produsul M_1 * ... * M_n
    return dp[1][n];
}