Go: package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"strconv"
)

var cache [100][100]int

func main() {
	sc := bufio.NewScanner(os.Stdin)
	sc.Split(bufio.ScanWords)
	sc.Scan()
	num, _ := strconv.Atoi(sc.Text())
	tables := []table{}
	for i := 0; i < num; i++ {
		sc.Scan()
		num1, _ := strconv.Atoi(sc.Text())
		sc.Scan()
		num2, _ := strconv.Atoi(sc.Text())
		t := table{num1, num2}
		tables = append(tables, t)
	}

	fmt.Println(minimum(0, len(tables)-1, tables))
}

type table struct {
	v int
	h int
}

func minimum(i int, j int, t []table) int {
	if i == j {
		return 0
	}

	// fmt.Printf("i:%v j:%v\n", i, j)
	if cache[i][j] != 0 {
		return cache[i][j]
	}

	min := math.MaxInt64
	for k := i; k < j; k++ {
		p := t[i].v
		n := t[k].h
		q := t[j].h
		val := minimum(i, k, t) + minimum(k+1, j, t) + p*n*q
		if val < min {
			min = val
		}
	}

	cache[i][j] = min
	return min
}

C++: 
#include <iostream>
using namespace std;

void MatrixChain(int, int[], int **, int **);
void print(int, int, int **);

int main()
{
    int n;
    cin >> n;
    int *tempP = new int[2 * n]; //p[0]为A1的行数；p[i]为Ai的列数
    
    int *p = new int[n + 1];    //p[0]为A1的行数；p[i]为Ai的列数
    int **m = new int *[n + 1]; //m[i][j]为Ai连乘到Aj的最少乘次数
    int **s = new int *[n + 1]; //s[i][j]为 Ai连乘到Aj的最优解的第一层断点
    for (int i = 1; i <= n; i++)
    {
        m[i] = new int[n + 1];
        s[i] = new int[n + 1];
    }
    
    for (int i = 0; i < 2 * n; i++)
    {
        cin >> tempP[i];
    }
    
    for (int i = 0; i <= n; i++)
    {
        p[i] = i == 0 ? tempP[0] : tempP[i*2-1];
    }
    
    // for (int i = 0; i <= n; i++)
    //     cin >> p[i];
    MatrixChain(n, p, m, s);
    cout    << m[1][n] << endl; //最优值存储在m[1][n]
        //print(1, n, s);
    
//    for (int idx = 1; idx <= n; idx++)
//    {
//        for (int jdx = 1; jdx <= n; jdx++)
//        {
//            cout << m[idx][jdx] << " ";
//        }
//        cout << endl;
//    }
    return 0;
}

void MatrixChain(int n, int p[], int **m, int **s)
{
    int i, j, k, temp;
    //以下双重循环对m[][]的上三角进行填表
    //填表顺序为自底向上，自左向右
    for (i = n; i >= 1; i--) //i表示行
    {
        for (j = i; j <= n; j++) //j表示列，因为只填上三角，所以j的初值为i
        {
            //以下按照矩阵连乘问题的递归公式来求每一个m[i][j]
            if (i == j)
            {
                m[i][j] = 0;
            }
            else
            {
                m[i][j] = m[i][i] + m[i + 1][j] + p[i - 1] * p[i] * p[j]; //若i与j不相等，m[i][j]的初值为断点为i时的最优值
                
                s[i][j] = i;                //记录当前断点位置为i
                for (k = i + 1; k < j; k++) //k用于尝试不同的断点
                {
                    temp = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
                    if (temp < m[i][j]) //当前k值作为Ai连乘到Aj的断点能获得更少计算量
                    {
                        m[i][j] = temp; //刷新最优值
                        s[i][j] = k;    //刷新相应断点
                    }
                }
            }
        }
    }
}

void print(int i, int j, int **s)
{
    if (i == j)
        cout << "A" << i;
    else
    {
        cout << "(";
        print(i, s[i][j], s);
        print(s[i][j] + 1, j, s);
        cout << ")";
    }
}

C++: #include <iostream>
#include <algorithm>
using namespace std;

int main(){
    int n, p[101], c[101][101], k; 
    cin >> n;
    for (int i=1; i<=n; i++) {
        cin >> p[i-1] >> p[i];
    }
    for (int i=1; i<=n; i++) {
        c[i][i] = 0;
    }
    for (int i=2; i<=n; i++) {
        for (int j=1; j<=n-i+1; j++) {
            k = j + i -1;
            c[j][k] = 2147483647;
            for (int l=j; l <=k-1; l++) {
            c[j][k] = min(c[j][k], c[j][l] + c[l+1][k] + p[j-1]*p[l]*p[k]);
            }
        }
    }
    cout << c[1][n] << endl;
}

C++: #include <iostream>
#include <vector>
using namespace std;
const int INF = 1001001001;

int main() {
    int n;
    cin  >> n;
    vector<int> p(n+1);
    int temp;
    for(int i=0; i<n-1; i++) {
        cin >> p[i] >> temp;
    }
    cin >> p[n-1] >> p[n];
    
    vector<int> a(n);
    vector< vector<int> > A(n,a);
    for(int i=0; i<n; i++) A[i][i] = 0;

    for(int l=2; l<=n; l++) {
        for(int i=0; i<n-l+1; i++) {
            int j = i+l-1;
            A[i][j] = INF;
            for(int k=i; k<j; k++) {
                int q = A[i][k] + A[k+1][j] + p[i]*p[k+1]*p[j+1];
                if(q<A[i][j]) A[i][j] = q;
            }
        }
    }

    cout << A[0][n-1] << endl;
    return 0;
}

C++: #include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <iostream>

struct Matrix
{
	int rows;
	int columns;
};

int main()
{
	int n;
	std::cin >> n;
	//There's n matrixes.
	
	if(n == 1)
	{
		std::cout << 0 << std::endl;
		return 0;
	}
	
	Matrix matrix[1 + n];
	
	for(int i = 1;i <= n;i++)
	{
		//cin >> r, rows >> c, columns.
		std::cin >> matrix[i].rows >> matrix[i].columns;
	}
	
	long long int DPMem[1 + n][1 + n] = {0};
	
	for(int i = 1;i <= n;i++)
		for(int j = 1;j <= n;j++)
			DPMem[i][j] = 9223372036854775807;
	
	//DP
	
	//init DPMem of M(i) * M(i) and M(i) * M(i + 1).
	for(int i = 1;i <= n - 1;i++)
	{
		DPMem[i][i] = 0;
		DPMem[i][i + 1] = matrix[i].rows * matrix[i].columns * matrix[i + 1].columns;
		
		//Debug.
		//printf("DPMem[%i][%i] = %lli \n",i,i + 1,DPMem[i][i + 1]);
	}
	DPMem[n][n] = 0;
	
	//Debug.
	//std::cout << std::endl;
	
	//DP main.
	for(int len = 3;len <= n;len++)		//len refers to length of multiplying matrix chain
	{
		//Debug.
		//printf("Length = %i \n",len);
		for(int head = 1;head + len - 1 <= n;head++)
		{
			int tail = head + len - 1;
			for(int mid = head;mid < tail;mid++)
			{
				//Debug.
				/*
				printf("DPMem[%i][%i] = %lli \n",head,tail,DPMem[head][tail]);
				printf("head = %i, mid = %i,mid + 1 = %i, tail = %i \n",head,mid,mid + 1,tail);
				*/
				
				DPMem[head][tail] = std::min(DPMem[head][tail],DPMem[head][mid] + DPMem[mid + 1][tail] + matrix[head].rows * matrix[mid].columns * matrix[tail].columns);
				
				//Debug.
				/*
				printf("DPMem[%i][%i] = %lli \n",head,mid,DPMem[head][mid]);
				printf("DPMem[%i][%i] = %lli \n",mid + 1,tail,DPMem[mid + 1][tail]);
				printf("matrix[%i].rows * matrix[%i].columns(matrix[%i].rows) * matrix[%i].columns = %i \n",head,mid,mid + 1,tail,matrix[head].rows * matrix[mid].columns * matrix[tail].columns);
				printf("DPMem[%i][%i] = %lli \n",head,tail,DPMem[head][tail]);
				std::cout << std::endl;
				*/
			}
		}
	}

	//Output.
	std::cout << DPMem[1][n] << std::endl;
	
	return 0;
}

C++: #include<bits/stdc++.h>
using namespace std;

typedef long long ll;

vector<ll> r(100);
vector<ll> c(100);
vector<vector<ll>> dp(101, vector<ll>(101,-1));

ll solve(ll a, ll b)
{
    if(dp.at(a).at(b) != -1){
        return dp.at(a).at(b);
    }
    if(b-a == 1){
        return dp.at(a).at(b) = 0;
    }else if(b-a == 2){
        return dp.at(a).at(b) = r.at(a)*c.at(a)*c.at(b-1);
    }else{
        vector<ll> tmp;
        ll i;
        for(i = a+1;i <= b-1;++i){
            ll tmp1 = solve(a, i);
            ll tmp2 = solve(i, b);
            tmp.push_back(tmp1 + tmp2 + r.at(a)*r.at(i)*c.at(b-1));
        }
        sort(tmp.begin(), tmp.end());
        return dp.at(a).at(b) = tmp.front();
    }
}

int main()
{
    ll i,j;
    ll n;
    cin >> n;
    for(i = 0;i < n;++i){
        cin >> r.at(i) >> c.at(i);
    }
    ll ans = solve(0,n);
    cout << ans << endl;
    return 0;
}

C++: #include<iostream>
using namespace std;
const int INF=1<<21;
int p[105];
int m[105][105];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)cin>>p[i-1]>>p[i];
    for(int i=1;i<=n;i++)m[i][i]=0;

        /* l==1时，是每两个相乘，l=3个时，是三个与剩下的几个相乘，l=4，是四个矩阵与剩下的
        相乘的最小*/
    for(int l=2;l<=n;l++)       //对于每个l都是用来变更  矩阵相乘大小的
    {
        for(int i=1;i<=n-l+1;i++)
        {
            int j=i+l-1;
            m[i][j]=INF;
            for(int k=i;k<=j-1;k++)
            {
                m[i][j]=min(m[i][j],m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j]);
            }
        }
    }
    cout<<m[1][n]<<endl;
    return 0;
}