Cod sursa(job #3239555)

Utilizator filipinezulBrain Crash filipinezul Data 6 august 2024 14:31:16
Problema Parantezare optima de matrici Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.35 kb
#include <bits/stdc++.h>
using namespace std;

/**
 * @brief dp[i][j] = numarul minim de inmultiri scalare cu
 * care se poate obține produsul Mi ∗ Mi+1 ∗ ... ∗ Mj
 * 
 * dp[i][j] = min(dp[i][k] + dp[k + 1][j] + d[i - 1] * d[k] * d[j]), k = i : j - 1
 */
class Task { // T = O(n ^ 3),  S = O(n ^ 2)
 public:
    void solve() {
        read_input();
        print_output(get_result());
    }

 private:
    int n;
    vector<int32_t> d;
    
    void read_input() {
        ifstream fin("podm.in");
        fin.tie(0);
        
        fin >> n;
        d.resize(n + 1);

        for (int i = 0; i <= n; i++) {
            fin >> d[i];
        }

        fin.close();
    }

    uint64_t get_result() {
        vector<vector<uint64_t>> dp(n + 1, vector<uint64_t> (n + 1, UINT64_MAX));
        
        // caz de baza 1: nu am ce înmulți
        for (int i = 1; i <= n; ++i) {
            dp[i][i] = 0ULL;
        }

        // caz de baza 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];  
        }
        
        // caz general
        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)
                    uint64_t 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); 
                }
            }
        }

        return dp[1][n];
    }

    void print_output(uint64_t result) {
        ofstream fout("podm.out");
        fout.tie(0);

        fout << result << "\n";
        fout.close();
    }
};

int main() {
    ios::sync_with_stdio(false);
    auto* task = new (nothrow) Task();

    if (!task) {
        cerr << "new failed\n";
        return -1;
    }

    task->solve();
    delete task;

    return 0;
}