Go: package main

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

type Matrix struct {
	r int // num of row
	c int // num of column
}

type Range struct {
	start int // index, inclusive
	end   int // index, inclusive
}

func calcMultiplication(x, y Matrix) (Matrix, int) {
	if x.c != y.r {
		panic("cannnot calculate")
	}
	return Matrix{x.r, y.c}, x.r * y.c * x.c
}

func calcMinMatrixChainMultiplication(matrices []Matrix, r Range, memo map[Range]int) (Matrix, int) {
	if v, ok := memo[r]; ok {
		return Matrix{matrices[0].r, matrices[len(matrices)-1].c}, v
	}
	if len(matrices) == 0 {
		panic("must not be empty")
	} else if len(matrices) == 1 {
		return matrices[0], 0
	} else if len(matrices) == 2 {
		return calcMultiplication(matrices[0], matrices[1])
	}

	var minCount int = math.MaxInt32

	for i := 0; i < len(matrices)-1; i++ {
		formerMatrices := matrices[:i+1]
		latterMatrices := matrices[i+1:]
		matF, countF := calcMinMatrixChainMultiplication(formerMatrices, Range{0, i}, memo)
		matL, countL := calcMinMatrixChainMultiplication(latterMatrices, Range{i + 1, len(matrices) - 1}, memo)
		_, countFL := calcMultiplication(matF, matL)
		count := countF + countL + countFL
		if count < minCount {
			minCount = count
		}
	}
	return Matrix{matrices[0].r, matrices[len(matrices)-1].c}, minCount
}

func main() {
	sc := bufio.NewScanner(os.Stdin)
	sc.Split(bufio.ScanWords)
	n, _ := nextInt(sc)
	matrices := make([]Matrix, n)
	for i := 0; i < n; i++ {
		r, _ := nextInt(sc)
		c, _ := nextInt(sc)
		matrices[i] = Matrix{r, c}
	}
	memo := make(map[Range]int)
	_, resultCount := calcMinMatrixChainMultiplication(matrices, Range{0, len(matrices) - 1}, memo)
	fmt.Println(resultCount)
}

func nextInt(sc *bufio.Scanner) (int, error) {
	sc.Scan()
	return strconv.Atoi(sc.Text())
}

C++: #include <cassert>
// #include <algorithm>
#include <iostream>
#include <vector>
#include <climits>

struct TSize
{
    int r;
    int c;
    TSize() : r(0), c(0) {}
    TSize(int Ar, int Ac)
     : r(Ar), c(Ac)
    {}
};

class TMcmSolver
{
    typedef std::vector<std::vector<int> > TMatrix;
    TMatrix FMemo;
    const std::vector<TSize>& FChain;

    static int Count(const TSize& Left, const TSize& Right)
    {
        return Left.r * Right.c * Left.c;
    }
    int Solve(int s, int l)
    {
        assert(s <= l);
        if(s == l) return 0;
        if(FMemo[s][l] != 0) return FMemo[s][l];
        if(s + 1 == l){
            FMemo[s][l] = Count(FChain[s], FChain[l]);
        }else{
            int min = INT_MAX;
            for(int i = s+1; i < l; ++i){
                int c = Solve(s, i) + Count(TSize(FChain[s].r, FChain[i].c), TSize(FChain[i+1].r, FChain[l].c)) + Solve(i+1, l);
                min = std::min(min, c);
            }
            FMemo[s][l] = min;
        }
        return FMemo[s][l];
    }
public:
    TMcmSolver(const std::vector<TSize>& Chain)
     : FChain(Chain)
    {
        FMemo.resize(Chain.size());
        for(std::size_t i = 0; i < FMemo.size(); ++i){
            FMemo[i].resize(Chain.size(), 0);
        }
    }
    int Answer()
    {
        return Solve(0, FMemo.size()-1);
    }
    void Print()const
    {
        for(std::size_t s = 0; s < FMemo.size(); ++s){
            for(std::size_t l = 0; l < FMemo[0].size(); ++l){
                std::cout << FMemo[s][l] << '\t';
            }
            std::cout << '\n';
        }
    }
};

int main()
{
    int n;
    std::cin >> n;
    if(n == 1){
        std::cout << 0 << std::endl;
        return 0;
    }
    std::vector<TSize> Chain(n);
    for(int i = 0; i < n; ++i){
        std::cin >> Chain[i].r >> Chain[i].c;
    }
    TMcmSolver Solver(Chain);
    
    std::cout << Solver.Answer() << std::endl;
    // Solver.Print();
    return 0;
}

C++: #include <bits/stdc++.h>

using namespace std;

typedef long long int ll;
typedef pair<ll, ll> pll;

#define FOR(i, n, m) for(ll (i)=(m);(i)<(n);++(i))
#define REP(i, n) FOR(i,n,0)
#define OF64 std::setprecision(10)

const ll MOD = 1000000007;
const ll INF = (ll) 1e15;

ll dp[105][105];

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll N;
    cin >> N;
    vector<pll> A(N);
    REP(i, N) {
        cin >> A[i].first >> A[i].second;
    }

    REP(i, N + 1) {
        REP(j, N + 1) {
            dp[i][j] = INF;
        }
        dp[i][i] = 0;
    }

    FOR(len, N, 1) {
        REP(left, N) {
            if (left + len >= N)
                break;
            REP(i, len) {
                ll mul = dp[left][left + i] + dp[left + i + 1][left + len];
                mul += A[left].first * A[left + i].second * A[left + len].second;
                dp[left][left + len] = std::min(dp[left][left + len], mul);
            }
        }
    }

    cout << dp[0][N - 1] << endl;
    return 0;
}

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

int calc(const vector<pair<int, int> >& M, int idx_b, int idx_e,
         vector<vector<int> >& Memo) {
    if (idx_b == idx_e) return 0;
    if (Memo[idx_b][idx_e]) return Memo[idx_b][idx_e];
    int min = 2e9;
    for (int i = idx_b; i < idx_e; i++) {
        int val  = calc(M, idx_b, i, Memo) + calc(M, i + 1, idx_e, Memo)
                   + M[idx_b].first * M[i].second * M[idx_e].second;
        if (val < min) min = val;
    }
    return Memo[idx_b][idx_e] = min;
}

int main(){
    int n;
    cin >> n;
    vector<pair<int, int> > M;

    for (int i = 0; i < n; i++) {
        pair<int, int> input;
        cin >> input.first >> input.second;
        M.push_back(input);
    }
    vector<int> tmp(n, 0);
    vector<vector<int> > Memo(n, tmp);
    cout << calc(M, 0, M.size() - 1, Memo) << endl;

    return 0;
}

C++: #include <stdio.h>
#include <limits.h>
int main(){
  int n,p[101],i,j,k,l,x,m[101][101];
  scanf("%d",&n);
  for(i=1;i<=n;i++)scanf("%d %d",&p[i-1],&p[i]);
  for(i=1;i<=n;i++)m[i][i]=0;
  for(l=2;l<=n;l++){
    for(i=1;i<=n-l+1;i++){
      j=i+l-1;
      m[i][j]=INT_MAX;
      for(k=i;k<j;k++){
	x=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
	if(m[i][j]>x)m[i][j]=x;
      }
    }
  }
  printf("%d\n",m[1][n]);
  return 0;
}

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

ll dp[101][101];

int main()
{
	int n;
	cin >> n;
	for(int i = 0;i<=n;i++)
	{
		for(int j = 0;j<=n;j++)
		{
			dp[i][j] = 1e18;
		}
	}
	for(int i =0 ;i<=n;i++)
	{
		dp[i][i] = 0;
		dp[i][i+1] = 0;

	}
	vector<ll> r(n),c(n);
	for(int i = 0;i<n;i++)cin >> r[i] >> c[i];

	for(int i =0;i<n-1;i++)
	{
		dp[i][i+2] = r[i] * c[i] * c[i+1];
	}
	for(int haba = 3;haba<=n;haba++)
	{
		for(int i = 0;i<=n-haba;i++)
		{
			for(int j = 1;j<haba;j++)
			{
				ll now = dp[i][i+j]+dp[i+j][i+haba]+r[i]*r[i+j]*c[i+haba-1];
				//if(i==0&&haba==4)
				//{
					//cout<<';'<<i<<' '<<i+j<<' '<<i+haba<<endl;
					//cout<<dp[i][i+j]<<' '<<dp[i+j][i+haba]<<';'<<r[i]<<' '<<r[i+j]<<' '<<c[i+haba-1]<<endl;
					//cout<<' '<<now<<endl;
				//}
				dp[i][i+haba] = min(dp[i][i+haba],now);
			}
		}
	}
	//for(int i = 0;i<n-1;i++){cout<<dp[i][i+2]<<endl;}
	//cout<<dp[1][4]<<endl;
	cout<<dp[0][n]<<endl;
}