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 <stdio.h>
#include <limits.h>
 
#define MAX 100
 
int A[MAX],B[MAX][MAX],n;
    
main(){
  int i,r,c;
 
  scanf("%d",&n);
 
  for(i=0; i<n; i++)
    {
      scanf("%d %d",&r,&c);
      A[i]=r;
      A[i+1]=c;
    }
 
  MatrixChain();
 
  return 0;
}

void MatrixChain()
{
 
  int i,j,k,l,cost;
 
  for(i=1; i<=n; i++)
    {
      B[i][i]=0;
    }
 
  for(l=2; l<=n; l++)
    {
      for(i=1; i<=n-l+1; i++)
    {
      j=i+l-1;
      B[i][j]=INT_MAX;
 
      for(k=i; k<=j-1; k++)
        {
          cost=B[i][k]+B[k+1][j]+A[i-1]*A[k]*A[j];
          if(cost < B[i][j])
        {
          B[i][j]=cost;
        }
        }
    }
    }
  printf("%d\n",B[1][n]);
}

C++: #include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<map>
#include<set>
#include<cstdio>
#include<cmath>
#include<deque>
#include<numeric>
#include<queue>
#include<stack>
#include<cstring>
#include<limits>
#include<functional>
#include<unordered_set>
#include<iomanip>
#include<cassert>
#include<regex>
#include<bitset>
#include<complex>
#include<chrono>
#include<random>
#define rep(i,a) for(int i=(int)0;i<(int)a;++i)
#define rrep(i,a) for(int i=(int)a-1;i>=0;--i)
#define REP(i,a,b) for(int i=(int)a;i<(int)b;++i)
#define RREP(i,a,b) for(int i=(int)a-1;i>=b;--i)
#define pb push_back
#define eb emplace_back
#define all(x) x.begin(),x.end()
using ll=long long;
constexpr ll mod = 1e9 + 7;
constexpr ll INF = 1LL << 60;

ll gcd(ll n, ll m) {
	ll tmp;
	while (m!=0) {
		tmp = n % m;
		n = m;
		m = tmp;
	}
	return n;
}

ll lcm(ll n, ll m) {
	return abs(n) / gcd(n, m)*abs(m);//gl=xy
}
 
template<class T> inline bool chmin(T& a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template<class T> inline bool chmax(T& a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
 
using namespace std;

void solve(){
  int n;
  cin>>n;
  vector<ll>r(n),c(n);
  rep(i,n)cin>>r[i]>>c[i];
  vector<vector<ll>>dp(n+1,vector<ll>(n+1,INF));
  rep(i,n)dp[i][i+1]=0;
  REP(w,2,n+1){
    rep(i,n){
      int j=i+w;
      if(j>n)continue;
      for(int k=i+1;k<j;++k){
        chmin(dp[i][j],dp[i][k]+dp[k][j]+r[i]*r[k]*c[j-1]);
      }
    }
  }
  cout<<dp[0][n]<<"\n";
}

int main(){
	ios::sync_with_stdio(false);
  cin.tie(0);
	cout<<fixed<<setprecision(15);
  solve();
	return 0;
}

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

int main(){
  int n,b[200],bb[200][200],a,c,min;
  cin>>n;
  for(int i=1;i<n;i++){
    cin>>a>>c;
    b[i]=a;
  }
  cin>>a>>c;
  b[n]=a;
  b[n+1]=c;
  for(int i=1;i<=n;i++){
    bb[i][i]=0;
    if(i<n)bb[i+1][i]=b[i]*b[i+1]*b[i+2];
  }
  for(int i=2;i<=n-1;i++){
    for(int j=1;j<=n-i;j++){
      min=1000000000;
      for(int l=j;l<j+i;l++){
	if(min>bb[l][j]+bb[j+i][l+1]+b[j]*b[l+1]*b[j+i+1])
	  min=bb[l][j]+bb[j+i][l+1]+b[j]*b[l+1]*b[j+i+1];
      }
      bb[j+i][j]=min;
    }
  }

  cout<<bb[n][1]<<endl;
  return 0;
}

/*
for(int i=0;i<=n;i++){
for(int j=0;j<=n;j++){
cout<<bb[i][j]<<" ";
}
}

*/

C++: #include "bits/stdc++.h"
#define Rep(i,n) for(int i=0;i<(int)(n);i++)
#define For(i,n1,n2) for(int i=(int)(n1);i<(int)(n2);i++)
#define REP(i,n) for(ll i=0;i<(ll)(n);i++)
#define RREP(i,n) for(ll i=((ll)(n)-1);i>=0;i--)
#define FOR(i,n1,n2) for(ll i=(ll)(n1);i<(ll)(n2);i++)
#define RFOR(i,n1,n2) for(ll i=((ll)(n1)-1);i>=(ll)(n2);i--)
#define all(a)  (a).begin(),(a).end()
#define IOS std::cin.tie(0),std::ios::sync_with_stdio(false)

namespace idaten {

	using namespace std;
	using ll = int_fast64_t;
	using ull = uint_fast64_t;
	using P = std::pair<int64_t, int64_t>;
	template<typename T1, typename T2> inline bool chmin(T1& a, T2 b) { if (a > b) { a = b; return 1; }return 0; }
	template<typename T1, typename T2> inline bool chmax(T1& a, T2 b) { if (a < b) { a = b; return 1; }return 0; }
	template<class Type>struct is_vector : std::false_type {};
	template<class ValueType, class Alloc>struct is_vector<std::vector<ValueType, Alloc>> : std::true_type {};
	template <typename T> inline std::ostream& operator << (std::ostream& out, const std::vector<T>& v) {
		if (v.empty())return out;
		constexpr bool is_vector_v = is_vector<T>::value;
		if (is_vector_v)for (auto itr = v.begin(); itr != v.end();)out << (*itr), out << ((++itr != v.end()) ? "\n" : "");
		else for (auto itr = v.begin(); itr != v.end();)out << (*itr), out << ((++itr != v.end()) ? " " : "");
		return out;
	}
	inline void put() {}
	template<class T> inline void put(const T& first) { std::cout << first << "\n"; }
	template<class T, class... N> inline void put(const T& first, const N& ... rest) { std::cout << first << " "; put(rest...); }
	inline void putn() {}
	template<class T, class... N> inline void putn(const T& first, const N& ... rest) { std::cout << first << "\n"; putn(rest...); }

	void solve() {
		IOS;
		int n;
		cin >> n;
		vector<int> a(n + 1);
		int b;
		REP(i, n) {
			cin >> a[i] >> b;
		}
		a[n] = b;
		vector<vector<int>> dp(n + 1, vector<int>(n + 1, 0));
		RREP(i, n + 1) {
			FOR(j, i + 2, n + 1) {
				int tmp = INT_MAX;
				FOR(k, i + 1, j) {
					chmin(tmp, dp[i][k] + dp[k][j] + a[i] * a[k] * a[j]);
				}
				dp[i][j] = tmp;
					
			}
		}
		put(dp[0][n]);
	}
		
	
} // namespace idaten

int main() {
	idaten::solve();
	return 0;
}

C++: #include <iostream>
using namespace std;
static const int INFTY=(1<<21);

int main() {
  std::ios::sync_with_stdio(false);
  cout.tie(0);
  cin.tie(0);
  int n;
  cin>>n;
  int p[n+1];
  for (int i=1; i<=n; i++) {
    cin>>p[i-1]>>p[i];
  }
  int m[n+1][n+1];
  for (int i=1; i<=n; i++) {
    m[i][i]=0;
  }
  for (int l=2; l<=n; l++) {
    for (int i=1; i<=n-l+1; i++) {
      int j=i+l-1;
      m[i][j]=INFTY;
      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;
}