Go: package main

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

//util
var sc = bufio.NewScanner(os.Stdin)

func nextStr() string {
	sc.Scan()
	return sc.Text()
}

func nextInt() int {
	sc.Scan()
	i, e := strconv.Atoi(sc.Text())
	if e != nil {
		panic(e)
	}
	return i
}

func printList(list []int) {
	buf := bufio.NewWriter(os.Stdout)
	for _, v := range list {
		buf.Write([]byte(fmt.Sprintf(" %d", v)))
	}
	buf.Write([]byte("\n"))
	buf.Flush()
}

//solve
//単純な場合
func matrixChainMultiplication() {
	//行列が1つだけのとき
	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] = 1 << 21
			//kまでで区切る
			for 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])
			}
		}
	}
}

func max(a, b int) int {
	if a > b {
		return a
	} else {
		return b
	}
}

func min(a, b int) int {
	if a > b {
		return b
	} else {
		return a
	}
}

const MAX = 100

var n int
var p [MAX + 1]int

//m[i][j]: Mi * Mi+1 * ... * Mjを計算するときに必要なスカラー乗算の最小回数
var m [MAX + 1][MAX + 1]int

func main() {
	sc.Split(bufio.ScanWords)
	n = nextInt()
	for i := 1; i <= n; i++ {

		p[i-1] = nextInt() //行数
		p[i] = nextInt()   //列数
	}

	matrixChainMultiplication()
	fmt.Println(m[1][n])
}

C++: #include<stdio.h>
#include<algorithm>

#define MAX 1000
#define INFINITY 2000000000

int A[MAX];
int m[MAX][MAX];
int n;

void minimumCount() {
    for (int i = 0; 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] = INFINITY;
            for (int k = i; k < j; ++k) {
                m[i][j] = std::min(m[i][j], m[i][k] + m[k+1][j] + A[i-1] * A[k] * A[j]);
            }
        }
    }
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d %d", &A[i - 1], &A[i]);
    }
    minimumCount();
    printf("%d\n", m[1][n]);
}

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

static const int N=100;

int main(){
    int n,p[N+1],m[N+1][N+1];
    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;
    for(int l=2; l<=n; l++){
        for(int i=1; i<=n-l+1; i++){
            int j = i + l - 1;
            m[i][j] = (l<<21);
            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;
}

C++: #include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=0; i<(n); i++)
#define FOR(i,x,n) for(int i=x; i<(n); i++)
#define ALL(n) begin(n),end(n)
#define MOD (1000000007)
#define INF (1e9)
#define INFL (1e18)
 
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
template<class T>using arr=vector<vector<T>>;
template<class T>void pr(T x){cout << x << endl;}
template<class T>void prvec(vector<T>& a){rep(i, a.size()-1){cout << a[i] << " ";} cout << a[a.size()-1] << endl;}
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
template<class T>void prarr(vector<vector<T>>& a){
rep(i, a.size()){
rep(j, a[i].size()){
cout << a[i][j]; printf(" ");}
printf("\n");} printf("\n");}

vector<ll> row, col;
arr<ll> dp;
ll ans = INFL;
int n; 

ll dfs(int l, int r){
    // printf("%lld %lld\n", l, r);
    if(dp[l][r]!=INFL) return dp[l][r];
    if(l==r) return dp[l][r] = 0;
    if(r==l+1) return dp[l][r] = row[l] * col[l] * col[r];

    ll tmp = INFL;
    FOR(k, l, r){
        chmin(tmp, dfs(l, k) + dfs(k+1, r) + row[l] * col[k] * col[r]);
    }

    return dp[l][r] = tmp;
}

int main()
{
    cin >> n;
    row.resize(n); col.resize(n);
    rep(i, n){
        cin >> row[i] >> col[i];
    }
    dp.assign(n, vector<ll>(n, INFL));

    ans = dfs(0, n-1);
    
    // prarr(dp);
    pr(ans);
    return 0;}

C++: #include <iostream>
#include <array>
#include <limits>

using namespace std;

struct MatrixDims {
    int row;
    int col;
    MatrixDims() {}
    MatrixDims(int row, int col) : row(row), col(col) {}
};

array<MatrixDims, 100> matrix_dims;
array<array<int, 100>, 100> dp;

int get_min(int row, int col) {
    int min = numeric_limits<int>::max();
    for (int j = row; j < col; ++j) {
        int sum = dp[row][j] + dp[j+1][col] + matrix_dims[row].row * matrix_dims[j].col * matrix_dims[col].col;
        if (sum < min) min = sum;
    }
    return min;
}

int main()
{
    int n;
    cin >>  n;
    for (int i = 0; i < n; ++i) {
        int row, col;
        cin >> row >> col;
        matrix_dims[i] = MatrixDims(row, col);
    }
    dp.fill({});
    
    for (int endpt = 1; endpt < n; ++endpt) {
        for (int diag_i = 0; (endpt + diag_i) < n; ++diag_i) {
            dp[diag_i][diag_i + endpt] = get_min(diag_i, endpt + diag_i);
        }
    }
    cout << dp[0][n-1] << endl;
}

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

static const long N = 100;

int main(){
	long n, p[N + 1], m[N + 1][N + 1];
	cin >> n;
	for (long i = 1; i <= n; i++){
		cin >> p[i - 1] >> p[i];
	}

	for (long i = 1; i <= n; i++) m[i][i] = 0;
	for (long l = 2; l <= n; l++){
		for (long i = 1; i <= n - l + 1; i++){
			long j = i + l - 1;
			m[i][j] = (1 << 21);
			for (long 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;
}

C++: #include<stdio.h>
#include<map>
#include<array>

using lr = std::pair<int, int>;
using lr_map = std::map<lr, int>;

int rc(int mat[], lr_map &dp, int n, int rest_n, int limit);

int main()
{
	int n, mat[101]{}, count{};
	lr_map dp;

	scanf("%d%d%d", &n, mat, mat + 1);
	for (int i = 1; i < n; ++i)
		scanf("%d%d", mat + i, mat + i + 1);

	printf("%d\n", rc(mat, dp, 0, n, 2000000000));

	return 0;
}

int rc(int mat[], lr_map &dp, int left, int right, int min)
{
	if (left + 1 == right) return 0;
	if (dp.find(lr{ left, right }) != dp.end()) return dp[lr{ left, right }];

	for (int mid = left + 1; mid < right; ++mid)
	{
		int tmp = mat[left] * mat[mid] * mat[right];
		tmp += rc(mat, dp, left, mid, min);
		if (tmp > min) continue;

		tmp += rc(mat, dp, mid, right, min);
		if (tmp > min) continue;

		min = tmp;
	}
	dp[lr{ left, right }] = min;
	return min;
}

C++: 4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 
#include <iostream>
#include <algorithm>
 
using namespace std;
 
static const int N = 100;
 
int main() {
    int n, p[N + 1], m[N + 1][N + 1];
    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;
    for( int l = 2; l <= n; l++ ) {
        for(int i = 1; i <= n-l+1; i++) {
            int j = i + l - 1;
            m[i][j] = (1 << 21);
            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;
}

C++: #include <cstdio>
#include <algorithm>
using namespace std;
int m[107], dp[107][107];
int main() {
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
    	scanf("%d%d", &m[i], &m[i + 1]);
	}
	for (int l = 2; l <= n; l++) {
		for (int i = 1; i <= n - l + 1; i++) {
			int j = i + l - 1;
			dp[i][j] = 1e9 + 7;
			for (int k = i; k < j; k++) {
				dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + m[i - 1] * m[k] * m[j]);
			}
		}
	}
	printf("%d\n", dp[1][n]);
    return 0;
}