Problem:
 Score : 100 points    Problem Statement There are N slimes lining up in a row.
Initially, the i -th slime from the left has a size of a_i .  Taro is trying to combine all the slimes into a larger slime.
He will perform the following operation repeatedly until there is only one slime:   Choose two adjacent slimes, and combine them into a new slime. The new slime has a size of x + y , where x and y are the sizes of the slimes before combining them. Here, a cost of x + y is incurred. The positional relationship of the slimes does not change while combining slimes.   Find the minimum possible total cost incurred.      Constraints  All values in input are integers.  2 \leq N \leq 400  1 \leq a_i \leq 10^9         Input Input is given from Standard Input in the following format:  N  a_1  a_2  \ldots  a_N       Output Print the minimum possible total cost incurred.        Sample Input 1 4
10 20 30 40      Sample Output 1 190  Taro should do as follows (slimes being combined are shown in bold):   ( 10 , 20 , 30, 40) → ( 30 , 30, 40)  ( 30 , 30 , 40) → ( 60 , 40)  ( 60 , 40 ) → ( 100 )        Sample Input 2 5
10 10 10 10 10      Sample Output 2 120  Taro should do, for example, as follows:   ( 10 , 10 , 10, 10, 10) → ( 20 , 10, 10, 10)  (20, 10 , 10 , 10) → (20, 20 , 10)  (20, 20 , 10 ) → (20, 30 )  ( 20 , 30 ) → ( 50 )        Sample Input 3 3
1000000000 1000000000 1000000000      Sample Output 3 5000000000  The answer may not fit into a 32-bit integer type.       Sample Input 4 6
7 6 8 6 1 1      Sample Output 4 68  Taro should do, for example, as follows:   (7, 6, 8, 6, 1 , 1 ) → (7, 6, 8, 6, 2 )  (7, 6, 8, 6 , 2 ) → (7, 6, 8, 8 )  ( 7 , 6 , 8, 8) → ( 13 , 8, 8)  (13, 8 , 8 ) → (13, 16 )  ( 13 , 16 ) → ( 29 )

Solution (Python):
from sys import setrecursionlimit
setrecursionlimit(1<<30)
def f(i,j,d):
  if i>=j:
    return 0
  if z[i][j]==-1:
    q=1<<64
    for k in xrange(i,j):
      q=min(q,s[j+1]-s[i]+f(i,k,d)+f(k+1,j,d))
    z[i][j]=q
  return z[i][j]
n=input()
a=map(int,raw_input().split())
s=[0]
for i in a:
  s.append(s[-1]+i)
z=[[-1]*n for i in xrange(n)]
print f(0,n-1,{})

Solution (Python):
n = int(input())
a = list(map(int,input().split()))
dp = [[0 for _ in range(n)] for _ in range(n)]
size = [[0 for _ in range(n)] for _ in range(n)]
for i in range(n):
  size[i][i] = a[i]
for i in range(n-1):
  for j in range(1,n-i):
    size[i][i+j] = size[i][i+j-1]+a[i+j]
for i in range(1,n):
  for j in range(0,n-i):
    mn = float("inf")
    for k in range(i):
      if mn > dp[j][j+k] + dp[j+k+1][j+i]:
        mn = dp[j][j+k] + dp[j+k+1][j+i]
    dp[j][j+i] = mn+ size[j][j+i]
print(dp[0][n-1])

Solution (Python):
n = int(input())
ns = list(map(int, input().split()))
dp = [[0] * n for i in range(n)]
cur = [0]
cnt = 0
for i in ns:
    cnt += i
    cur.append(cnt)

for i in range(n-1, -1, -1):
    for j in range(i + 1, n):
        dp[i][j] = min(dp[i][k] + dp[k + 1][j] for k in range(i, j)) + cur[j+1] - cur[i]
print(dp[0][-1])

Solution (Python):
def main():
    N = int(input())
    a = list(map(int, input().split()))
    inf = 10 ** 13
    dp = [[0]*N for i in range(N)]
    s = [0]*(N+1)
    for i, x in enumerate(a):
        s[i+1] = s[i]+a[i]
        dp[i][i] = 0
    for i in range(N-2, -1, -1):
        DP = dp[i]
        si = s[i]
        for j in range(i+1, N):
            tmp = s[j+1] - si
            D = inf
            for k in range(i, j):
                cost = DP[k]+dp[k+1][j]
                if D > cost:
                    D = cost
            DP[j] = D + tmp
    print(dp[0][N-1])
main()

Solution (Python):
def main():
    import sys
    from itertools import accumulate
    input = sys.stdin.readline
    N = int(input())
    a = list(map(int, input().split()))
    inf = 10 ** 13
    dp = [[0]*N for i in range(N)]
    s = [0] + list(accumulate(a))
    for i, x in enumerate(a):
        dp[i][i] = 0
    for i in range(N-2, -1, -1):
        DP = dp[i]
        si = s[i]
        for j in range(i+1, N):
            tmp = s[j+1] - si
            D = inf
            for k in range(i, j):
                cost = DP[k]+dp[k+1][j]
                if D > cost:
                    D = cost
            DP[j] = D + tmp
    print(dp[0][N-1])


main()

Solution (Python):
def main():
    N = int(input())
    a = list(map(int, input().split()))

    dp = [[10**13]*N for i in range(N)]
    s = [0] * (N+1)
    for i in range(N):
        s[i+1] = s[i] + a[i]
        dp[i][i] = 0
    for i in range(N-1, -1, -1):
        for j in range(i+1, N):
            tmp = s[j+1] - s[i]
            for k in range(i, j):
                dp[i][j] = min(dp[i][j], dp[i][k]+dp[k+1][j] + tmp)

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


main()

Solution (Python):

import sys

sys.setrecursionlimit(10 ** 8)
INF = 1 << 62


def solve(N: int, a: "List[int]"):
    dp = [[INF] * N for _ in range(N + 1)]
    cumsize = [0] * (N + 1)
    for i in range(1, N + 1):
        cumsize[i] = cumsize[i - 1] + a[i - 1]

    def mincost(length, head):
        if head + length > N:
            return INF
        if dp[length][head] < INF:
            return dp[length][head]
        base_cost = cumsize[head + length] - cumsize[head]
        if length == 1:
            dp[length][head] = 0
            return 0
        cost = INF
        split_point = head
        for j in range(1, length):
            if split_point + j >= N:
                continue
            c = mincost(j, head) + mincost(length - j, head + j)
            if cost > c:
                cost = c
        cost += base_cost
        dp[length][head] = cost
        return cost

    return mincost(N, 0)


def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word

    tokens = iterate_tokens()
    N = int(next(tokens))  
    a = [int(next(tokens)) for _ in range(N)]  
    print(solve(N, a))


if __name__ == "__main__":
    main()

Solution (Python):
import numpy as np

N = int(input())
A = [0] + list(map(int, input().split()))
S = np.cumsum(A, dtype=np.int64)

dp = np.zeros((N + 1, N + 1), dtype=np.int64)
for length in range(2, N + 1):
    for l in range(N - length + 1):
        r = length + l
        dp[l][r] = np.amin(dp[l, l + 1:r] + dp[l + 1:r, r]) + S[r] - S[l]
print(dp[0][N])

Solution (Python):
import itertools

N = int(input())
A = tuple(map(int, input().split()))
S = [0] + list(itertools.accumulate(A))

dp = [[0] * (N + 1) for _ in range(N + 1)]
for length in range(2, N + 1):
    for l in range(N - length + 1):
        r = length + l
        dp[l][r] = min(dp[l][m] + dp[m][r] for m in range(l + 1, r)) + S[r] - S[l]
print(dp[0][N])

Solution (Python):
N=int(input())
A=[0]+list(map(int,input().split()))



C=[0]*(N+1)
C[1]=A[1]
for index1 in range(2,N+1):
    C[index1]+=C[index1-1]+A[index1]

DP=[[0]*(N+1) for index2 in range(N+1)]


def mincost(i,j):   
    global A
    global DP

    if DP[i][j]>0:
        return DP[i][j]
    if i==j:
        return DP[i][j]
    else:
        res=float('inf')
        sum=C[j]-C[i-1]
        for k in range(i,j):
            res=min(res,mincost(i,k)+mincost(k+1,j)+sum)
        DP[i][j]=res
        return DP[i][j]

mincost(1,N)
print(DP[1][N])

Solution (Python):
n = int(input())
*A, = map(int, input().split())
S = [0]
for i in range(n):
    S.append(S[-1]+A[i])
DP = [[None for j in range(n+1)] for i in range(n)]
def dp(i, j):
    if j <= i+1:
        return 0
    if DP[i][j] != None:
        return DP[i][j]
    DP[i][j] = S[j]-S[i]+min([dp(i, k)+dp(k, j) for k in range(i+1, j)])
    return DP[i][j]
print(dp(0, n))

Solution (Python):
n = int(input())
*A, = map(int, input().split())
S = [0]
for i in range(n):
    S.append(S[-1]+A[i])
DP = [[None for r in range(n+1)] for l in range(n)]
def dp(l, r):
    if r <= l+1:
        return 0
    if DP[l][r] != None:
        return DP[l][r]
    DP[l][r] = S[r]-S[l]+min([dp(l, i)+dp(i, r) for i in range(l+1, r)])
    return DP[l][r]
print(dp(0, n))

Solution (Python):
N = int(input())
A = list(map(int, input().split()))

from itertools import groupby, accumulate, product, permutations, combinations

def solve(N,A):
    dp = [[0]*N for _ in range(N)] 
    cum = [0]+list(accumulate(A))
    for k in range(1,N):
        for i in range(N-k):
            j = i + k
            dp[i][j] = cum[j+1]-cum[i] + min([dp[i][i+l]+dp[i+l+1][j] for l in range(k)])
    ans = dp[0][N-1]
    return ans
print(solve(N,A))

Solution (Python):


import sys
sys.setrecursionlimit(1000000000)
input = sys.stdin.readline
INF=10**15
n=int(input())
a=list(map(int,input().split()))
b=[0]*(n+1)
for i in range(n):
    b[i+1]=b[i]+a[i]
dp=[[-1]*n for i in range(n)]
for i in range(n):
    dp[i][i]=0
def memo(i,j):
    if dp[i][j]>=0:
        return dp[i][j]
    ans=INF
    for k in range(i,j):
        ans=min(ans,memo(i,k)+memo(k+1,j))
    dp[i][j]=ans+b[j+1]-b[i]
    return dp[i][j]
print(memo(0,n-1))

Solution (Python):

n=int(input())
a=list(map(int,input().split()))
INF=10**15
dp=[[0]*n for i in range(n)]
for i in range(n):
    dp[i][i]=a[i]

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


for i in range(1,n):
    for j in range(n-i):
        ans=INF
        for k in range(j,i+j):
            ans=min(ans,dp[j][k]+dp[k+1][i+j])
        dp[j][i+j]+=ans
print(dp[0][-1])

Solution (Python):

n=int(input())
a=list(map(int,input().split()))
INF=10**15
dp=[[0]*n for i in range(n)]
for i in range(n):
    dp[i][i]=a[i]

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


for i in range(n-1):
    for j in range(i+1,n):
        ans=INF
        x=j-i-1
        for k in range(x,j):
            ans=min(ans,dp[x][k]+dp[k+1][j])
        dp[x][j]+=ans
print(dp[0][-1])

Solution (Python):


n=int(input())
a=list(map(int,input().split()))
INF=10**15
dp=[[0]*n for i in range(n)]
for i in range(n):
    dp[i][i]=a[i]
for i in range(n-1):
    for j in range(i+1,n):
        dp[i][j]=dp[i][j-1]+a[j]

for i in range(n-1):
    for j in range(i+1,n):
        ans=INF
        
        for k in range(j-i-1,j):
            ans=min(ans,dp[j-i-1][k]+dp[k+1][j])
        if i<n-2:
            dp[j-i-1][j]+=ans
        else:
            print(ans)

Solution (Python):
n = int(input())
*A, = map(int, input().split())


DP = [[None for r in range(n+1)] for l in range(n)]
S = [0]
for i in range(n):
    S.append(S[-1]+A[i])


def dp(l, r):
    
    if r <= l+1:
        DP[l][r] = 0
    if DP[l][r] != None:
        return DP[l][r]
    
    DP[l][r] = S[r]-S[l]+min([dp(l, i)+dp(i, r) for i in range(l+1, r)])
    return DP[l][r]


print(dp(0, n))

Solution (Python):
n = int(input())
*A, = map(int, input().split())


inf = 10**20
DP = [[None for r in range(n+1)] for l in range(n)]
S = [0]
for i in range(n):
    S.append(S[-1]+A[i])


def f(l, r):
    if r <= l+1:
        DP[l][r] = 0
    if DP[l][r] != None:
        return DP[l][r]
    DP[l][r] = S[r]-S[l]+min([f(l, i)+f(i, r) for i in range(l+1, r)])
    return DP[l][r]


print(f(0, n))

Solution (Python):
N=int(input())
A=list(map(int,input().split()))
asum=[0 for i in range(0,N+1)]
for i in range(1,N+1):
    asum[i]=A[i-1]+asum[i-1]

dp=[[0 for i in range(0,N+1)] for j in range(0,N)]

for i in range(0,N):
    if N>i+1:
        dp[i][2]=A[i]+A[i+1]

for j in range(3,N+1):
    for i in range(0,N):
        if N>i+j-1 and j!=3:
            ans=min(A[i]+asum[i+j]-asum[i+1]+dp[i+1][j-1],asum[i+j-1]-asum[i]+dp[i][j-1]+A[i+j-1])
            test=min(dp[i][k]+dp[i+k][j-k]+asum[i+k]-asum[i]+asum[i+j]-asum[i+k] for k in range(2,j-1))
            dp[i][j]=min(ans,test)
        elif N>i+j-1:
            dp[i][j]=min(A[i]+asum[i+j]-asum[i+1]+dp[i+1][j-1],asum[i+j-1]-asum[i]+dp[i][j-1]+A[i+j-1])


print(dp[0][N])

Solution (Python):
import sys
sys.setrecursionlimit(10 ** 7)
read = sys.stdin.buffer.read 
inp = sys.stdin.buffer.readline
def inpS(): return inp().rstrip().decode()
readlines = sys.stdin.buffer.readlines 
MOD = 10**9+7


def resolve():
    def dfs(l, r):
        if r - l == 1:
            dp[l][r] = A[l] + A[r]
            return dp[l][r]

        if dp[l][r] is not None:
            return dp[l][r]

        ret = 1<<60
        for x in range(l,r):
            cost = cum_A[r+1] - cum_A[l]
            ret = min(ret, dfs(l, x) + dfs(x+1, r) + cost)

        dp[l][r] = ret
        return ret

    N = int(input())
    A = list(map(int, input().split()))
    cum_A = [0]*(N+1)
    for i in range(N):
        cum_A[i+1] = cum_A[i] + A[i]

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

    return print(dfs(0, N-1))

if __name__ == "__main__":
    resolve()

Solution (Python):
def resolve():
    N = int(input())
    A = list(map(int, input().split()))
    cum_A = [0]*(N+1)
    for i in range(N):
        cum_A[i+1] = cum_A[i] + A[i]

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

    for l in range(2, N+1):
        
        for left in range(N-l+1):
            right = left + l-1
            
            cost = cum_A[right+1] - cum_A[left]
            for k in range(left, right):
                tmp = dp[left][k] + dp[k+1][right] + cost
                dp[left][right] = min(dp[left][right], tmp)

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

if __name__ == "__main__":
    resolve()

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


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


def main():
    N = int(input())
    A = inpl()
    cumA = [0] * (N + 1)
    for i, a in enumerate(A):
        cumA[i + 1] = cumA[i] + a
    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):
            dp[i][i + L] = cumA[i + L + 1] - cumA[i] + min(dp[i][i + k] + dp[i + k + 1][i + L] for k in range(L))
        
    print(dp[0][N - 1])


if __name__ == '__main__':
    main()

Solution (Python):
n = int(input())
a = [int(i) for i in input().split()]

dp = [[10 ** 18] * n for _ in range(n)]
dp[0] = [0] * n

s = [0]
for i in a:
    s.append(s[-1]+i)


for i in range(1, n):
    for j in range(n):
        if i + j < n:
            b = 10 ** 18
            for k in range(i):
                l = i - k - 1
                b = min(b, dp[k][j]+dp[l][j+k+1])
            dp[i][j] = b + s[i+j+1]-s[j]

print(dp[-1][0])

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
INF = 9223372036854775807

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()
    A = iip()
    SA = [0]

    cur = 0
    for i in A:
        cur += i
        SA.append(cur)

    
    size = [[0 for _ in range(N)] for _ in range(N)]
    for i in range(N):
        for j in range(i, N):
            size[i][j] = int(SA[j+1]-SA[i])

    

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

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

            if l==r:
                dp[l][r] = 0
            else:
                dp[l][r] = min(dp[l][r],
                               dp[l+1][r] + size[l][l] + size[l+1][r],
                               dp[l][r-1] + size[r][r] + size[l][r-1])

            for k in range(l, r):
                dp[l][r] = min(dp[l][r], dp[l][k] + dp[k+1][r] + size[l][k] + size[k+1][r])

    
    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):  
    if isinstance(l, list):
        l = l[0] 
    assert isinstance(l, int)
    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)
        return
    keta = max([len(str(i)) for i in itertools.chain.from_iterable(s)])
    print("--------")
    for i in s:
        print([str(j).rjust(keta) for j in i])
    print("--------")


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):
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
INF = 18446744073709551615

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()
    A = iip()
    SA = [0]

    cur = 0
    for i in A:
        cur += i
        SA.append(cur)

    
    size = [[0 for _ in range(N)] for _ in range(N)]
    for i in range(N):
        for j in range(i, N):
            size[i][j] = int(SA[j+1]-SA[i])

    

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

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

            if l==r:
                dp[l][r] = 0
            else:
                dp[l][r] = min(dp[l][r],
                               dp[l+1][r] + size[l][l] + size[l+1][r],
                               dp[l][r-1] + size[r][r] + size[l][r-1])

            for k in range(l, r):
                dp[l][r] = min(dp[l][r], dp[l][k] + dp[k+1][r] + size[l][k] + size[k+1][r])

    
    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):  
    if isinstance(l, list):
        l = l[0] 
    assert isinstance(l, int)
    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)
        return
    keta = max([len(str(i)) for i in itertools.chain.from_iterable(s)])
    print("--------")
    for i in s:
        print([str(j).rjust(keta) for j in i])
    print("--------")


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()