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 in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include<bits/stdc++.h>
using namespace std;
#define loop(i,x,z) for (int i=x;i<z;i++)
using ll = long long;
const int M = 1000000007;
/*int n, w;
ll dp[1002][1002];
bool A[1002][1002];
ll travel(int x,int y)
{
	if (x > n || y > w) return 0;
	//cout << "yup";
	if (dp[x][y] >= 0 || !A[x][y])
	{
		if (dp[x][y] >= 0)
			return dp[x][y];
		else return 0;
	}
	//cout << "yup";
	dp[x][y] = (travel(x + 1, y) + travel(x, y + 1)) % M;
	return dp[x][y];
}
int main()
{
	cin >> n >> w;
	memset(dp, -1, sizeof(dp));
	loop(i,1,n+1)
		loop(j, 1, w + 1)
			{
				char a;
				cin >> a;
				if (a == '.') A[i][j] = 1;
			}
	dp[n][w] = 1;
	cout << travel(1,1);
}*/
/*long double A[3001];
int n, t;
vector<vector<long double>>dp(3001, vector<long double>(3001, 1.000000000));
int main()
{
	cin >> n;
	
	loop(i, 1, n + 1)
	{
		cin >> A[i];
		A[i] *= 1000000000;
		A[i] /= 1000000000;
	}
	t = n / 2;
	loop(i, 1, n+1)
	{
		dp[i][0] = dp[i - 1][0] * A[i];
		dp[i][i] = dp[i - 1][i - 1] * (1 - A[i]);
		loop(j, 1, i)
		{
			dp[i][j] = dp[i - 1][j] * A[i] + dp[i - 1][j - 1] * (1 - A[i]);
		}
	}
	loop(i, 0, t + 1)
	{
		A[0] += dp[n][i];
		//cout << dp[n][i] << " ";
	}
	//cout << endl;

	cout <<fixed << setprecision(12) << A[0];
}*/
/*int n, l, A[100];
int dp[100002][2];
bool game(int sum, int turn)
{
	if (sum < 0)
	{
		return 0;
	}
	if (dp[sum][turn] != -1)
	{
		if(dp[sum][turn])
		return 0;
		return 1;
	}
	loop(i, 0, n)
		if(sum-A[i]==0 || game(sum - A[i], (turn + 1) % 2))
			dp[sum][turn] = 1;
	if(dp[sum][turn]>0)return 0;
	dp[sum][turn]=0;
	return 1;
}
int main()
{
	cin >> n >> l;
	memset(dp, -1, sizeof(dp));
	loop(i, 0, n)
	{
		cin >> A[i];
	}
	game(l,0);
	if (dp[l][0])
	{
		cout<<"First";
		return 0;
	}
	cout << "Second";
} */
/*ll n, A[3001], dp[3002][3002];
ll pref[3002], suf[3002];
ll play(int x, int y)
{
	if (x == y)
	{
		dp[x][y] = A[x];
		return 0;
	}
	if (dp[x][y]) return (pref[n]-pref[x-1]-suf[y+1]-dp[x][y]);
	dp[x][y]= max(A[x] + play(x + 1, y), A[y] + play(x, y - 1));
	//cout << x << "," << y <<":"<< pref[n] - pref[x - 1] - suf[y + 1] << " ";
	return pref[n] - pref[x - 1] - suf[y + 1] - dp[x][y];
}
int main()
{
	cin >> n;
	loop(i, 1, n + 1)
	{
		cin >> A[i];
		pref[i] += A[i]+pref[i-1];
	}
	loop(i, 1, n + 1)
	{
		suf[n + 1 - i] += A[n + 1 - i]+suf[n - i+2];
	}
	loop(i, 1, n + 1)
	{
		//cout << pref[i] << "," << suf[i] << " ";
	}
	cout<<pref[n]-(ll)2*play(1, n);
}*/
/*const int nax = 305;
double p[nax][nax][nax], ev[nax][nax][nax];
// ev[a][b][c] - the expected number of operations so far to get to state (a,b,c)
// easier: p-bility of getting to this state at all, p[a][b][c]

int main() {
	int n;
	scanf("%d", &n);
	vector<int> cnt(4);
	for (int i = 0; i < n; ++i) {
		int x;
		scanf("%d", &x);
		++cnt[x];
	}
	p[cnt[1]][cnt[2]][cnt[3]] = 1;
	for (int c = n; c >= 0; --c) {
		for (int b = n; b >= 0; --b) {
			for (int a = n; a >= 0; --a) {
				if (a == 0 && b == 0 && c == 0) {
					continue;
				}
				if (a + b + c > n) {
					continue;
				}
				// dp[a][b][c]

				double p_waste = (double)(n - (a + b + c)) / n;
				// p_waste + p_waste^2 + ... = S
				// 1 + S = S / p_waste
				double ev_waste = p_waste / (1 - p_waste) + 1;
				ev[a][b][c] += ev_waste * p[a][b][c];

				// remove 1 -> dp[a-1][b][c]
				// we will eventually choose one of a+b+c
				if (a != 0) {
					double p_go = (double)a / (a + b + c);
					p[a - 1][b][c] += p[a][b][c] * p_go;
					ev[a - 1][b][c] += ev[a][b][c] * p_go;
				}

				// remove 2 -> dp[a+1][b-1][c]
				if (b != 0) {
					double p_go = (double)b / (a + b + c);
					p[a + 1][b - 1][c] += p[a][b][c] * p_go;
					ev[a + 1][b - 1][c] += ev[a][b][c] * p_go;
				}

				// remove 3
				if (c != 0) {
					double p_go = (double)c / (a + b + c);
					p[a][b + 1][c - 1] += p[a][b][c] * p_go;
					ev[a][b + 1][c - 1] += ev[a][b][c] * p_go;
				}
			}
		}
	}
	printf("%.10lf\n", ev[0][0][0]); // + cnt[1] + 2 * cnt[2] + 3 * cnt[3]);
}*/
int n,A[402];
ll dp[402][402];
ll sum (int L, int R)
{
	ll s=0;
	loop(i, L, R+1) s += (ll)A[i];
	return s;
}
int main()
{
	cin >> n;
	loop(i, 0, n)
	{
		cin >> A[i];
	}
	for (int L=n-1;L>=0;L--)
	{
		loop(R, L, n)
		{
			if (L == R) dp[L][L] = 0;
			else
			{
				dp[L][R] = 1e18;
				ll s = sum(L, R);
				loop(i, L, R )
					dp[L][R] = min(dp[L][R],dp[L][i] + dp[i + 1][R] + s);
			}
		}
	}
	cout << dp[0][n-1];
}