Problem:
Matrix-chain Multiplication The goal of the matrix-chain multiplication problem is to find the most efficient way to multiply given $n$ matrices $M_1, M_2, M_3,...,M_n$. Write a program which reads dimensions of $M_i$, and finds the minimum number of scalar multiplications to compute the maxrix-chain multiplication $M_1M_2...M_n$. Input In the first line, an integer $n$ is given. In the following $n$ lines, the dimension of matrix $M_i$ ($i = 1...n$) is given by two integers $r$ and $c$ which respectively represents the number of rows and columns of $M_i$. Output Print the minimum number of scalar multiplication in a line. Constraints  $1 \leq n \leq 100$  $1 \leq r, c \leq 100$  Sample Input 1 6
30 35
35 15
15 5
5 10
10 20
20 25 Sample Output 1 15125

Solution (Python):
N = int(input())
RC = [0] * N
for i in range(N):
  RC[i] = list(map(int, input().split()))
  
dp = [[float("inf")] * (N + 1) for _ in range(N + 1)]
for l in range(N + 1):
  for r in range(l, N + 1):
    if abs(l - r) <= 1:
      dp[l][r] = 0
    elif abs(l - r) == 2:
      dp[l][r] = RC[l][0] * RC[l][1] * RC[l + 1][1]
      


now = 3
while now <= N:
  for l in range(N + 1):
    
    r = l + now
    if r <= N:
      for k in range(l + 1, r):
        dp[l][r] = min(dp[l][r], dp[l][k] + dp[k][r] + RC[l][0] * RC[k][0] *RC[r - 1][1])
  now += 1
        
print(dp[0][N])

Solution (Python):
import sys

N = int(input())
R = [0]*N
C = [0]*N
for i in range(N):
    R[i], C[i] = map(int, input().split())

INF = 10**18
m = [[INF]*N for i in range(N)]
for i in range(N):
    m[i][i] = 0
for l in range(1, N):
    for i in range(N-l):
        a0 = R[i]
        c0 = C[i+l]
        m[i][i+l] = min(a0*C[j]*c0 + m[i][j] + m[j+1][i+l] for j in range(i, i+l))
print(m[0][N-1])

Solution (Python):
N = int(input())
R = [0]*N
C = [0]*N
for i in range(N):
    R[i], C[i] = map(int, input().split())

INF = 10**18
dp = [[INF]*N for i in range(N)]
for i in range(N):
    dp[i][i] = 0
for l in range(1, N):
    for i in range(N-l):
        a0 = R[i]
        c0 = C[i+l]
        dp[i][i+l] = min(a0*C[j]*c0 + dp[i][j] + dp[j+1][i+l] for j in range(i, i+l))
print(dp[0][N-1])

Solution (Python):
n = int(input())
p=[]
for i in range(n):
    s,c = map(int,input().split())
    if i == 0:
        p.append(s)
    p.append(c)


m = [[0 for _ in range(n+1)] for _ in range(n+1)]

for j in range(1, n):
    for i in range(1, n+1):
        if i+j > n:
            break
        if i != i+j:
            m[i][i+j] = min([m[i][k] + m[k+1][i+j] + p[i+j]*p[k]*p[i-1] for k in range(i,i+j)])

print(m[1][n])

Solution (Python):
import sys
INFTY=sys.maxsize

def main(n,m,p):
    
    

    for i in range(1,n+1):
        m[i][i]=0

    for l in range(1,n):
        for i in range(1,n-l+1):
            j=i+l
            m[i][j]=INFTY
            for k in range(i,j):
                m[i][j] = min(m[i][j], m[i][k] + m[k+1][j]+p[i-1]*p[k]*p[j])    
    print(m[1][n])


n=int(input())
p=[]
k,l=list(map(int,input().split()))
i=1
p.append(k)
p.append(l)
while(i<n):
    l,m=list(map(int,input().split()))
    p.append(m)
    i+=1

m=[]
for i in range(n+1):
    mm=[0]*(n+1)
    m.append(mm)

main(n,m,p)

Solution (Python):



import sys

sys.setrecursionlimit(10 ** 6)
n = int(input())
r = []
for i in range(n):
    a, b = map(int, input().split())
    if i == 0:
        r.append(a)
        r.append(b)
    else:
        r.append(b)

dp = [[float('inf')] * (n + 1) for _ in range(n + 1)]




def chain_order(i, j):
    if i == j:
        return 0
    if dp[i][j] != float('inf'):
        return dp[i][j]
    for k in range(i, j):
        dp[i][j] = min(dp[i][j], chain_order(i, k) + chain_order(k + 1, j) + r[i - 1] * r[k] * r[j])
    return dp[i][j]



print(chain_order(1, len(r)-1))

Solution (Python):
INF = float('inf')
mm = [(-1,-1)]
n = int(input())
for _ in range(n):
    mm.append(tuple((map(int,input().split()))))

def scala(a,b,c):
    return mm[a][0] * mm[b][1] * mm[c][1] 

dp = [[INF for _ in range(n+1)] for _ in range(n+1)]

for i in range(1,n):
    dp[i][i+1] = mm[i][0] * mm[i+1][1] * mm[i][1]
    dp[i][i] = 0
dp[-1][-1] = 0

for d in range(2,n):
    for l in range(1,n-d+1):
        r = l + d
        for m in range(l,r):
            dp[l][r] = min(dp[l][m] + dp[m+1][r] + scala(l,r,m), dp[l][r])
print(dp[1][n])

Solution (Python):
from functools import lru_cache, reduce
from sys import stdin
from operator import mul

@lru_cache(maxsize=None)
def getMin(args:tuple):
    if len(args) == 2:
        return 0
    elif len(args) == 3:
        return reduce(mul, args)
    l = [(args[0:i+1], args[i:], args[0]*args[i]*args[-1]) for i in range(1, len(args)-1)]
    return min([getMin(v[0]) + getMin(v[1]) + v[2] for v in l])


n = int(input())
M = [tuple(map(int, line.split())) for line in stdin.readlines()]
R = tuple([M[0][0]] + [r[1] for r in M])
print(getMin(R))

Solution (Python):
from sys import stdin
from collections import deque
inf=float('inf')
def search(A,N):
    dp=[[inf for x in range(N+1)] for j in range(N+1)]

    p=[]
    for i in range(N+1):
        dp[i][i]=0
        if i>=1:
            if i==1:
                p.append(A[i][0])
                p.append(A[i][1])
            else:p.append(A[i][1])
    for l in range(2,N+1):
        for i in range(1,N-l+2):
            j=i+l-1
            for k in range(i,j):
                dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+p[i-1]*p[k]*p[j])
    return dp[1][-1]

N=int(input())
num_list = [[0, 0]]
for i in range(N):
    num_list.append(list(map(int,stdin.readline().strip().split())))
print(search(num_list,N))

Solution (Python):
n = int(input())
p = [0]*(n+1)

INF = 1000000000

for i in range(n):
    if i == 0:
        p[0],p[1] = map(int,input().split())
    else:
        tmp,p[i+1] = map(int,input().split())

dp = [[-1]*(n+2) for _ in range(n+2)]

def DFS(i,j):
    if dp[i][j] != -1:
        return dp[i][j]
    else:
        if j-i == 2:
            dp[i][j] = p[i]*p[i+1]*p[i+2]
            return dp[i][j]
        elif j-i == 1:
            dp[i][j] = 0
            return 0
        else:
            calculation_amount = INF
            for k in range(i+1,j):
                tmp = DFS(i,k) + DFS(k,j) + p[i]*p[j]*p[k] 
                calculation_amount = min(calculation_amount,tmp)
            dp[i][j] = calculation_amount
            return calculation_amount

print(DFS(0,n))

Solution (Python):
n = int(input())

M = []
for i in range(n):
    r, c = map(int, input().split())
    if i == 0: M.append(r)
    M.append(c)

dp = [[float("inf")] * (n+1) for _ in range(n+1)]

for i in range(1,n+1):
    dp[i][i] = 0

for l in range(2, n+1):
    for i in range(1,n-l+2):
        j = i + l -1
        for k in range(i, j):
            dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j] + M[i-1]*M[k]*M[j])

print(dp[1][n])

Solution (Python):
N=int(input())

input_=[N]
for n in range(N):
    input_.append(input())
    
P=[]
for n in range(N):
    P.append(int(input_[n+1].split()[0]))
    
P.append(int(input_[n+1].split()[1]))

M=[[0]*(N) for x in range(N)]

for n in range(1,N):
    for i in range(N-n):
        M[i][i+n]=10**100
        for k in range(i,i+n):
            P_0=P[i]
            P_1=P[k+1]
            P_2=P[i+n+1]
            M_=M[i][k]+M[k+1][i+n]+P_0*P_1*P_2
            M[i][i+n]=min(M[i][i+n],M_)
            
print(M[0][-1])

Solution (Python):
N = int(input())
R = [0]*N
C = [0]*N
for i in range(N):
    R[i],C[i] = map(int, input().split())


def solve(N,R,C):
    dp = [[float('inf')]*N for _ in range(N)]

    for i in range(N):
        dp[i][i]=0
    for i in range(N-1,-1,-1):
        for j in range(i+1,N):
            for k in range(i,j):
                dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]+R[i]*C[k]*C[j])
    ans = dp[0][N-1]
    return ans
print(solve(N,R,C))

Solution (Python):
import sys

n = int(sys.stdin.readline().strip())

p = [0]*(n+1)
dp = [[0]*(n+1) for _ in range(n+1)]

for i in range(n):
    p[i], p[i+1] = map(int, sys.stdin.readline().strip().split())



for l in range(2, n+1):
    
    for i in range(1, n-l+2):
        j = i + l - 1
        dp[i][j] = float("inf")
        
        for k in range(i, j):
            dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j] + p[i-1]*p[k]*p[j])

print(dp[1][n])

Solution (Python):
n = int(input())
nums = []
for _ in range(n):
    nums.append(tuple(map(int,input().split())))

dp = [[10**9]*n for _ in range(n)]
for i in range(n):
    dp[i][i] = 0


for l in range(2,n+1):
    for i in range(n-l+1):
        for k in range(l-1):
            
            dp[i][i+l-1] = min(dp[i][i+l-1],dp[i][i+k] + dp[i+k+1][i+l-1] + nums[i][0]*nums[i+k][1]*nums[i+l-1][1])
print(dp[0][n-1])

Solution (Python):
N = int(input())

for i in range(N):
    if i == 0:
        P = list(map(int, input().split()))
        continue
    P.append(int(input().split()[1]))

INF = 2 ** 32 - 1
dp = [[INF] * N for _ in range(N)]

for ij in range(N):
    dp[ij][ij] = 0

for l in range(1, N):
    for i in range(N):
        j = i + l
        if j >= N:
            continue
        for k in range(i, j):
            dp[i][j] = min(dp[i][k] + dp[k+1][j] + P[i] * P[j+1]*P[k+1],
                           dp[i][j])

print(dp[0][-1])

Solution (Python):
n = int(input())
p = [0]*(n+1)
for i in range(1,n+1): p[i-1],p[i] = map(int,input().split())
m = [[0]*(n+1) for _ in range(n+1)]

for l in range(2,n+1):
    
    
    
    
    for i in range(1,n-l+2):
        j = i+l-1
        m[i][j] = float("inf")
        
        for k in range(i,j):
            m[i][j] = min(m[i][j], m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j])
print(m[1][n])

Solution (Python):
n = int(input())
size = [int(i) for i in input().split()]
for _ in range(n - 1):
    _, a = map(int, input().split())
    size.append(a)
dp = [[0] * (n) for _ in range(n)]

for i in range(n):
    dp[i][i] = 0

for l in range(1, n):
    for i in range(n - l):
        j = i + l
        min = 10 ** 9
        for k in range(i, j):
            tmp = dp[i][k] + dp[k + 1][j] + size[i] * size[k + 1] * size[j + 1]
            if tmp < min:
                min = tmp
        dp[i][j] = min
print(dp[0][-1])

Solution (Python):
import sys
input = lambda: sys.stdin.readline().rstrip() 

def resolve():
    n = int(input())
    M = [list(map(int, input().split())) for _ in range(n)]

    
    dp = [[0]*(n+1) for _ in range(n)]

    
    for i in range(2, n+1):
        
        for j in range(n-i+1):
            tmp = []
            
            for k in range(j+1, j+i):
                tmp.append(M[j][0]*M[k][0]*M[j+i-1][1]+dp[j][k]+dp[k][j+i])
            dp[j][j+i] = min(tmp)

    print(dp[0][n])

if __name__ == '__main__':
    resolve()

Solution (Python):
def matrix_chain_multiplication(n):
    m = [[0 for x in range(n+1)] for y in range(n+1)]
    for l in range(2, n+1):
        for i in range(1, n-l+2):
            j = i + l - 1
            m[i][j] = float('inf')
            for k in range(i, j):
                m[i][j] = min(m[i][j], m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j])
    print(m[1][n])

p = []
n = int(input())

for i in range(n):
    listed_input = input().split()
    p.append(int(listed_input[0]))

p.append(int(listed_input[1]))

matrix_chain_multiplication(n)

Solution (Python):
n=int(input())
M=[list(map(int,input().split())) for _ in range(n)]

P=[M[0][0]]
for i in range(n):P.append(M[i][1])
DP=[[0 for _ in range(n)] for _ in range(n)]
for l in range(1,n):
    for i in range(n-l):
        j=i+l
        DP[i][j]=10**6
        for k in range(i,j):
            DP[i][j]=min(DP[i][j],DP[i][k]+DP[k+1][j]+P[i-1]*P[k]*P[j])
print(DP[0][-1])

Solution (Python):
n = int(input())

dimensions = []
for i in range(n):
    a, b = map(int, input().split())
    if i == 0:
        dimensions.append(a)
    dimensions.append(b)
inf = float('inf')
dps = [[inf for _ in range(n)] for _ in range(n)]
for i in range(n):
    dps[i][i] = 0
for i in range(n - 1, -1, -1):
    for j in range(i + 1, n):
        for k in range(i, j):
            dps[i][j] = min(dps[i][j],
                            dps[i][k] + dps[k + 1][j] + (dimensions[i] * dimensions[k + 1] * dimensions[j + 1]))
print(dps[0][n - 1])

Solution (Python):
N = int(input())
R = [0]*N
C = [0]*N
for i in range(N):
    R[i],C[i] = map(int, input().split())
    
DP = [[0 for _ in range(N)] for _ in range(N)]

for i in range(N):
    DP[i][i] = 0

for l in range(1, N):
    for r in range(N-l):
        ri = R[r]
        le = C[r+l]
        DP[r][r+l] = min(ri*C[k]*le+DP[r][k]+DP[k+1][r+l] for k in range(r, r+l))
print(DP[0][N-1])

Solution (Python):
import sys
sys.setrecursionlimit(10**8)
def ii(): return int(sys.stdin.readline())
def mi(): return map(int, sys.stdin.readline().split())
def li(): return list(map(int, sys.stdin.readline().split()))
def li2(N): return [list(map(int, sys.stdin.readline().split())) for _ in range(N)]
def dp2(ini, i, j): return [[ini]*i for _ in range(j)]
def dp3(ini, i, j, k): return [[[ini]*i for _ in range(j)] for _ in range(k)]




N = ii()
l = li2(N)


'''

dp = dp2(-1, N, N)
def rec(i, j):
    if dp[i][j] != -1:
        return dp[i][j]
    if i == j:
        dp[i][j] = 0
        return 0
    if j-i == 1:
        dp[i][j] = l[i][0] * l[i][1] * l[j][1]
        return dp[i][j]
    res = float('inf')
    for k in range(i, j):
        res = min(res, rec(i, k) + rec(k+1, j) + l[i][0] * l[k+1][0] * l[j][1])
    dp[i][j] = res
    return res

print(rec(0, N-1))
'''



dp = dp2(float('inf'), N, N)

for i in range(N):
    dp[i][i] = 0

for h in range(1, N):
    for i in range(N):
        if i+h < N:
            if h == 1:
                dp[i][i+h] = l[i][0] * l[i][1] * l[i+h][1]
            else:
                
                for r in range(i, i+h):
                    dp[i][i+h] = min(dp[i][i+h], dp[i][r]+dp[r+1][i+h]+l[i][0]*l[r+1][0]*l[i+h][1])

print(dp[0][N-1])

Solution (Python):
inf = 10**9+7
mod = 10**9+7
n = int(input())
rc = [list(map(int, input().split())) for i in range(n)]
dp = [[inf for j in range(n)]for i in range(n)]
for i in range(n):
    dp[i][i] = 0
for k in range(1,n):
    for i in range(0,n-k):
        for j in range(k):
            dp[i][i+k] = min(dp[i][i+k], dp[i][i+j] + dp[i+j+1][i+k] + rc[i][0]*rc[i+j][1]*rc[i+k][1])
print(dp[0][n-1])

Solution (Python):


from pprint import pprint
import sys

sys.setrecursionlimit(10 ** 6)
input = sys.stdin.buffer.readline

n = int(input())
l_dim = []
for _ in range(n):
    row, col = map(int, input().split())
    l_dim.append([row, col])








dp = [[-1 for j in range(n)] for i in range(n)]


def rec_dp(left, right):
    if dp[left][right] >= 0:
        
        return dp[left][right]
    if left == right:
        
        return 0

    row_left = l_dim[left][0]
    col_right = l_dim[right][1]
    res = float("inf")
    for k in range(left, right):
        col_k = l_dim[k][1]
        num = row_left * col_right * col_k
        res = min(res, rec_dp(left, k) + rec_dp(k + 1, right) + num)
    dp[left][right] = res

    return dp[left][right]


print(rec_dp(0, n - 1))

Solution (Python):
n = int(input())

N = 101

p = [0] * N
m = [[0] * N for _ in range(N)]

for i in range(1, n + 1):
	p[i - 1], p[i] = map(int, input().split())



for l in range(2, n + 1):
	for i in range(1, n - l + 2):
		j = i + l - 1
		m[i][j] = float('inf')
		for k in range(i, j):
			m[i][j] = min(m[i][j], m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j])

print(m[1][n])

Solution (Python):
import math
import copy
import sys
import fractions


import decimal
import heapq
import collections
import itertools
import bisect



sys.setrecursionlimit(100001)







def getInputIntList():
    outputDataList = []
    inputData = input().split()
    outputDataList = [int(n) for n in inputData]

    return outputDataList


def getSomeInputInt(n):
    outputDataList = []
    for i in range(n):
        inputData = int(input())
        outputDataList.append(inputData)

    return outputDataList


def getSomeInputListInt(n):
    inputDataList = []
    outputDataList = []
    for i in range(n):
        inputData = input().split()
        inputDataList = [int(n) for n in inputData]
        outputDataList.append(inputDataList)

    return outputDataList





n = int(input())

data_set = getSomeInputListInt(n)
data_set.insert(0, 0)

INF = sys.maxsize

dp = [[INF for _ in range(n+1)] for _ in range(n+1)]
for i in range(1, n+1):
    dp[i][i] = 0
next_dp = copy.deepcopy(dp)















for s in range(1, n):
    for i in range(1, n+1):
        j = i+s
        if j > n:
            break
        for k in range(i, j):
            if dp[i][k] < INF and dp[k+1][j] < INF:
                dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + data_set[i][0] * data_set[k][1] * data_set[j][1])

print(dp[1][n])

Solution (Python):

import sys
INF=10**9
MOD=10**9+7
input=lambda: sys.stdin.readline().rstrip()

def main():
    N=int(input())
    R,C=[0]*N,[0]*N
    A=[0]*(N+1)
    for i in range(N):
        A[i],A[i+1]=map(int,input().split())
    dp=[[INF]*N for _ in range(N)]
    dp[0]=[0]*N
    for i in range(N):
        for j in range(N-1-i):
            for k in range(i+1):
                dp[i+1][j]=min(dp[i+1][j],dp[i-k][j]+dp[k][i+1-k+j]+A[j]*A[j+i+1-k]*A[j+i+2])
    print(dp[-1][0])

if __name__ == '__main__':
    main()

Solution (Python):
import sys
from functools import lru_cache
input = sys.stdin.readline
sys.setrecursionlimit(2 * 10**6)


def inpl():
    return list(map(int, input().split()))


def main():
    @lru_cache(maxsize=None)
    def recur(i, j):
        
        if i == j:
            return 0
        for k in range(i, j):
            c = recur(i, k) + recur(k + 1, j) + P[i] * P[k + 1] * P[j + 1]
            if c < cost[i][j]:
                cost[i][j] = c
        return cost[i][j]

    N = int(input())
    RC = [inpl() for _ in range(N)]
    cost = [[float('inf')] * (N + 1) for a in range(N + 1)]
    P = [0] * (N + 1)
    for i, rc in enumerate(RC):
        P[i] = rc[0]
    P[N] = RC[N - 1][1]

    print(recur(0, N - 1))


if __name__ == '__main__':
    main()

Solution (Python):
N = int(input())
R = [0]*(N)
C = [0]*(N)
for i in range(N):
    R[i], C[i] = map(int, input().split())

dp = [[1<<60]*(N+1) for i in range(N+1)]
for i in range(N+1):
    dp[i][i] = 0

for le in range(1, N):
    for i in range(N-le):
        j = i + le

        for k in range(i, j):
            tmp = dp[i][k] + dp[k+1][j] + R[i]*C[k]*C[j]
            dp[i][j] = min(dp[i][j], tmp)
print(dp[0][N-1])

Solution (Python):
mod = 10 ** 9 + 7
mod2 = 2 ** 61 + 1
from collections import deque
import heapq
import time
from bisect import bisect_left, insort_left, bisect_right
import sys
import random
import itertools


def input():
    return sys.stdin.readline().strip("\n").strip(" ")

_NUMINT_ALL = list(range(10))
_START_TIME = time.time()
INDEX_KETA = 10**12

def main():
    ans = solve()

    if ans is True or ans is False:
        YesNo(ans)
    elif ans is None:
        return

    if isinstance(ans, tuple):
        split_print_space(ans)
    else:
        print(ans)


def solve():
    N = iip()
    M = iipt(N)
    R = [i[0] for i in M]
    R.append(M[-1][1])
    

    dp = [[10**6 for _ in range(N)] for _ in range(N)]

    for i in range(N):
        dp[i][i] = 0


    for d in range(1, N+1): 
        for l in range(N+1):
            r = l + d
            if r+1 > N:
                continue

            kouho = []
            for k in range(l+1, r+1):
                
                kouho.append(dp[l][k-1] + dp[k][r] + R[l]*R[r+1]*R[k])

            dp[l][r] = min(kouho)

            
            

    print(dp[0][-1])







def kiriage_warizan(a, b):
    return -(-a//b)

def iip(listed=False):  
    d = input().rstrip("\n").split()
    try:
        ret = [int(i) for i in d]
    except:
        ret = [int(i) if i in _NUMINT_ALL else i for i in d]
        if len(ret) == 1 and listed is False:
            return ret[0]

    if len(ret) == 1 and not listed:
        return ret[0]
    return ret

def iipt(l, listed=True, num_only=True):  
    if isinstance(l, list):
        l = l[0] 
    ret = []
    for i in range(l):
        ret.append(iip(listed=listed))
    return ret


def saidai_kouyakusuu(A):  
    l = len(A)
    while True:
        m = min(A)
        mx = max(A)
        if m == mx:
            return m

        for i in range(l):
            if A[i] % m == 0:
                A[i] = m
            else:
                A[i] %= m


def flatten(l):
    return list(itertools.chain.from_iterable(l))


def index_sorted(sorted_list, target):
    idx = bisect_left(sorted_list, target)
    if idx != len(sorted_list) and sorted_list[idx] == target:
        return idx
    else:
        return False


def time_debug_10percent():
    a = random.randint(0, 9)
    if a == 9:
        sys.exit()

def time_debug(t):
    time.sleep(_START_TIME + t - time.time())
    sys.exit()


def make_graph_edge_flat(N):  
    ret = []
    for i in range(N-1):
        a, b, c = iip()
        a -= 1
        b -= 1
        ret[a].append((b, c))
        ret[b].append((a, c))
    return ret


def sort_tuples(l, index):  
    if isinstance(l, list):
        l.sort(key=lambda x: x[index])
        return l
    else:
        l = list(l)
        return sorted(l, key=lambda x: x[index])


def count_elements(l):  
    d = {}
    for i in l:
        if i in d:
            d[i] += 1
        else:
            d[i] = 1
    return d


def safeget(l, index, default="exception"):  
    if index >= len(l):                      
        if default == "exception":
            raise Exception("".join(["safegetに不正な値 ", index, "が渡されました。配列の長さは", len(l), "です"]))
        else:
            return default
    elif index < 0:
        if default == "exception":
            raise Exception("".join(["safegetに不正な値 ", index, "が渡されました。負の値は許可されていません"]))
        else:
            return default
    else:
        return l[index]


def sortstr(s):  
    return "".join(sorted(s))


def iip_ord(startcode="a"):  
    if isinstance(startcode, str):
        startcode = ord(startcode)
    return [ord(i) - startcode for i in input()]


def YesNo(s):  
    if s:
        print("Yes")
    else:
        print("No")


def fprint(s):  
    if isinstance(s, int):
        print(s)
    keta = max([len(str(i)) for i in itertools.chain.from_iterable(s)])
    for i in s:
        print([str(j).zfill(keta) for j in i])


def bitall(N):  
    ret = []
    for i in range(2 ** N):
        a = []
        for j in range(N):
            a.append(i % 2)
            i //= 2
        ret.append(a)
    return ret

def split_print_space(s):  
    print(" ".join([str(i) for i in s]))


def split_print_enter(s):  
    print("\n".join([str(i) for i in s]))


def soinsuu_bunkai(n):  
    ret = []
    for i in range(2, int(n ** 0.5) + 1):
        while n % i == 0:
            n //= i
            ret.append(i)
        if i > n:
            break
    if n != 1:
        ret.append(n)
    return ret


def conbination(n, r, mod, test=False):  
    if n <= 0:
        return 0
    if r == 0:
        return 1
    if r < 0:
        return 0
    if r == 1:
        return n
    ret = 1
    for i in range(n - r + 1, n + 1):
        ret *= i
        ret = ret % mod

    bunbo = 1
    for i in range(1, r + 1):
        bunbo *= i
        bunbo = bunbo % mod

    ret = (ret * inv(bunbo, mod)) % mod
    if test:
        
        pass
    return ret


def inv(n, mod):  
    return power(n, mod - 2)


def power(n, p, mod_=mod):  
    if p == 0:
        return 1
    if p % 2 == 0:
        return (power(n, p // 2, mod_) ** 2) % mod_
    if p % 2 == 1:
        return (n * power(n, p - 1, mod_)) % mod_


def nibutan_func(func, target, left, right, side="left", seido = 1): 
    l = left
    r = right
    if seido == 1:
        x = (l + r) // 2
    else:
        x = (l + r) / 2
    while r-l > seido:
        
        if seido == 1:
            x = (l + r) // 2
        else:
            x = (l + r) / 2
        if func(x) == target:
            if side == "left":
                r=x
            else:
                l=x


        elif func(x) > target:
            r = x
        else:
            
            l = x

    
    if side == "left" and func(r) == target:
        return r
    elif side != "left" and func(l) == target:
        return l
    elif side == "left":
        return l
    else:
        return r


def nibutan_list(list_, target, side="left"):  
    if not isinstance(list_, list):
        list_ = list(list_)

    l = 0
    r = len(list_)
    x = (l + r) // 2
    while r-l > 1:
        x = (l+r)//2
        if list_[x] == target:
            return x
        elif list_[x] > target:
            r = x
        else:
            l = x

    if side == "left" or list_[x] == target:
        return l
    else:
        return r


class UfTree():
    def __init__(self, maxnum):
        self.parent = list(range(maxnum))
        self._size = [1] * maxnum
        self.rank = [0] * maxnum

    def size(self, a):
        return self._size[self.root(a)]

    def root(self, a):
        rank = 0
        cur = a
        while True:
            if self.parent[cur] == cur:
                
                
                return cur
            else:
                self.parent[cur] = self.parent[self.parent[cur]]
                cur = self.parent[cur]
                rank += 1

    def unite(self, a, b):
        ra = self.root(a)
        rb = self.root(b)
        if ra == rb:
            return self

        self._size[ra] += self._size[rb]
        self.parent[rb] = ra
        return self

if __name__ == "__main__":
    main()

Solution (Python):
n=int(input())
m=[]
for i in range(n-1):
    tmp=list(map(int,input().split()))
    m.append(tmp[0])
m.extend(list(map(int,input().split())))
dp=[[10**9]*n for i in range(n)]
for i in range(n):
    dp[i][i]=0
for W in range(1,n):
    for l in range(n-W):
        r=l+W
        for k in range(l,r+1):
            dp[l][r]=min(dp[l][r],m[l]*m[k]*m[r+1]+dp[l][k-1]+dp[k][r])
print(dp[0][n-1])

Solution (Python):

import functools

INF = float('inf')
@functools.lru_cache(maxsize=None)
def rec(l, r):
    if l + 1 == r:
        return 0
    ret = INF
    for mid in range(l+1, r):
        ret = min(ret, rec(l, mid) + rec(mid, r)+R[l]*R[mid]*C[r-1])
    return ret


if __name__ == "__main__":
    N = int(input())
    R = []
    C = []
    for _ in range(N):
        r, c = list(map(int, input().split()))
        R.append(r)
        C.append(c)

    print(rec(0, N))

Solution (Python):


n = int(input())
p = [-1 for i in range(n + 1)]
M = [[-1 for i in range(n + 1)] for i in range(n + 1)]

for i in range(1, n + 1):
    l, m = (int(i) for i in input().split())
    p[i - 1] = l
    p[i] = m

for i in range(1, n + 1):
    M[i][i] = 0

for l in range(2, n + 1):
    for i in range(1, n - l + 2):
        j = i + l - 1
        M[i][j] = 2000000000
        for k in range(i, j):
            M[i][j] = min(M[i][j], M[i][k] + M[k + 1][j] + p[i - 1] * p[k] * p[j])

print(M[1][n])

Solution (Python):
N = int(input())
matrices = [tuple(map(int, input().split())) for _ in range(N)]
R, C = zip(*matrices)
dp = [[float('inf')] * N for _ in range(N)]
for i in range(N): dp[i][i] = 0
for l in range(1, N):
    for i in range(N-l):
        r, c = R[i], C[i+l]
        dp[i][i+l] = min(r * C[j] * c + dp[i][j] + dp[j+1][i+l] for j in range(i, i+l))
print(dp[0][N-1])

Solution (Python):
INF = 1145141919810364364334

n = int(input())
p = []
for i in range(n):
    a,b = map(int,input().split())
    if i==0:
        p.append(a)
        p.append(b)
    else:
        p.append(b)
    
cost = [[INF] * (n+1) for i in range(n+1)]
for i in range(n+1):
    cost[i][i] = 0
    
for l in range(2,n+1):
    for i in range(1,n-l+2):
        j = i+l-1
        for k in range(i,j):
            cost[i][j] = min(cost[i][j] , cost[i][k] + cost[k+1][j] + p[i-1]*p[k]*p[j])
            
print(cost[1][n])

Solution (Python):
n=int(input())
a= [list(map(int, input().split())) for i in range(n)]
a+=a

INF=10**12
dp=[[INF]*(2*n+1) for i in range(2*n+1)]
ans=0
for i in range(n):
    for l in range(2*n-i):
        r=i+l
        if l==r:
            dp[l][r]=0
        else:
            for k in range(l,r):
                dp[l][r]=min(dp[l][k]+dp[k+1][r]+a[l][0]*a[k][1]*a[r][1],dp[l][r])


print(dp[0][n-1])

Solution (Python):
N = int(input())
rc = [list(map(int, input().split())) for _ in range(N)]

DP = [[(0, -1, -1)]*(N) for _ in range(N)]
DP[0] = [(0, r, c) for r, c in rc]

for i in range(1, N):
    for j in range(N-i):
        lis = []
        for k in range(i):
            s, r, c = DP[k][j]
            s2, r2, c2 = DP[i-k-1][j+k+1]
            lis.append((r*c*c2+s+s2, r, c2))
        DP[i][j] = min(lis)
print(DP[-1][0][0])

Solution (Python):
def Matrix_Chain_Multiplication(M, p, N):
    
    for l in range(2, N + 1):
        for i in range(1, N - l + 1 + 1):
            j = i + l - 1

            M[i][j] = 500000000

            for k in range(i , j):
                M[i][j] = min(M[i][j], M[i][k] + M[k + 1][j] + p[i - 1] * p[k] * p[j])
    
    return M[1][N]

def Main():
    N = int(input())

    p = [0 for i in range(N+1)]
    M = [[0]*(N+1) for i in range(N+1) ] 

    i = 0
    for n in range(N):
        r, c = map(int, input().split())

        if n == 0:
            p[i] = r
            i += 1
            p[i] = c
            i += 1
        else:
            p[i] = c
            i += 1

    print(Matrix_Chain_Multiplication(M, p, N))

Main()

Solution (Python):

N, *A = map(int, open(0).read().split())
A = A[0::2]+[A[-1]]

INF = float('inf')
dp = [[INF]*(N) for _ in [0]*(N)]


rg = range(N)

for i in rg:
    dp[i][i] = 0


for l in range(1, N):
    for i in rg:
        j = i + l
        if j >= N:
            continue
        for k in range(i, j):
            dp[i][j] = min(
                dp[i][j],
                dp[i][k] + dp[k+1][j] + A[i]*A[k+1]*A[j+1]
            )

print(dp[0][N-1])

Solution (Python):
import sys
input = sys.stdin.buffer.readline
sys.setrecursionlimit(10 ** 7)

N = int(input())
RC = [list(map(int, input().split())) for _ in range(N)]

memo = [[-1] * (N + 1) for _ in range(N + 1)]
inf = 10**18


def mult(l, r):
    """
    半開区間[l, r)
    """
    if memo[l][r] != -1:
        return memo[l][r]
    if r - l <= 1:
        memo[l][r] = 0
        return 0

    res = inf
    for m in range(l + 1, r):
        prod = RC[l][0] * RC[m - 1][1] * RC[r - 1][1]
        tmp = mult(l, m) + mult(m, r) + prod
        res = min(res, tmp)
    memo[l][r] = res
    return res


ans = mult(0, N)
print(ans)

Solution (Python):
n = int(input())

r = [0] * n
c = [0] * n

for i in range(n):
    r[i], c[i] = map(int, input().split())

dp = [[float("inf")] * n for _ in range(n)]

for i in range(n):
    dp[i][i] = 0

for gap in range(1, n):
    for s in range(n):
        e = s + gap
        if e >= n:
            continue
        for k in range(s, e):
            dp[s][e] = min(dp[s][e], dp[s][k] + dp[k + 1][e] + r[s] * c[k] * c[e])

print(dp[0][n - 1])

Solution (Python):
def resolve():
    
    
    def matrix_chain_multiplication(n):
        """
        連鎖行列積問題：
        n 個の行列について、行列 M_i の次元が与えられたとき、
        積 M_1 M_2...M_n の計算に必要なスカラー乗算の最小の回数を返す
        """
        m = [[0 for x in range(n + 1)] for y in range(n + 1)]
        for l in range(2, n + 1):
            for i in range(1, n - l + 2):
                j = i + l - 1
                m[i][j] = 99000001
                for k in range(i, j):
                    m[i][j] = min(m[i][j], m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j])
        return m[1][n]

    
    
    p = []

    
    n = int(input())

    
    
    for i in range(n):
        listed_input = input().split()
        p.append(int(listed_input[0]))

    p.append(int(listed_input[1]))

    print(matrix_chain_multiplication(n))


resolve()