#include <stdio.h>
#include <stdlib.h>
#define INF 0x3f3f3f3f
#define MAXN 501
void citeste_date_despre_matrici(int *N, int *p)
{
FILE *fd = fopen("podm.in", "r");
fscanf(fd, "%d", N);
int i;
for (i = 0; i <= (*N); i++) fscanf(fd, "%d", &p[i]);
fclose(fd);
}
void parantezare_optima_matrici(int N, int *p, int (*m)[MAXN])
{
int i;
for (i = 1; i <= N; i++)
m[i][i] = 0; // parantezare de matrici in grupuri de cate 1
int offset, j, k;
for (offset = 2; offset <= N; offset++) {
for (i = 1; i <= N - offset + 1; i++) {
j = offset + i - 1;
m[i][j] = INF;
for (k = i; k < j; k++) {
int var = m[i][k] + m[k + 1][j] + p[i - 1] * p[j] * p[k];
if (m[i][j] > var) m[i][j] = var;
}
}
}
}
int main()
{
int N; // numarul de matrici ce trebuiesc inmultite
int p[MAXN]; // dimensiunile fiecarei matrice: A[i] -> p[i - 1] x p[i]
citeste_date_despre_matrici(&N, p);
int m[MAXN][MAXN];
/**
* m[i][j] = numarul minim de inmultiri efectuate pentru a inmulti sirul de
* matrici cu indicii cuprinsi intre i...j, unde 1 <= i <= j <= N
* Obs.: m[i][j] se descompune in m[i][k] + m[k + 1][j] + p[i - 1] * p[j] * p[k],
* unde k este astfel ales incat m[i][j] sa fie minim
* Exemplu: m[1][N] = costul minim necesar inmultirii matricelor 1..k + cel necesar
* inmultirii matricelor (k + 1)..N, la care se adauga costul inmultirii ultimelor
* doua matrice rezultate prin inmultirea primelor k si a celorlalte (k+1)..N
*/
parantezare_optima_matrici(N, p, m);
FILE *fdout = fopen("podm.out", "w");
fprintf(fdout, "%d\n", m[1][N]);
return 0;
}