#include<bits/stdc++.h>
using namespace std;
const int N=310;
int n;
int a[N];//记录每堆石子的质量
int s[N];//记录前缀和
int f[N][N];//f[l][r]代表把l到r合并成一堆的最小代价。
int main()
{
memset(f,0x3f,sizeof(f)); //把数组f初始化为无穷大。
cin>>n;
for(int i=1;i<=n;i++) {
cin>>a[i];
s[i]=s[i-1]+a[i];//计算n堆石子的前缀和。
f[i][i]=0;//合并每一堆石子的代价为0.
}
for(int len=2;len<=n;len++){//枚举不同区间长度
for(int l=1;l+len-1<=n;l++){//枚举不同起点
int r=l+len-1;//区间终点。
for(int k=l;k<r;k++){//枚举不同切点。
f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]+s[r]-s[l-1]);
}
}
}
cout<<f[1][n]<<endl;
}
#include<bits/stdc++.h>
using namespace std;
const int N=1005;
char s[1001];
int f[N][N];
int main()
{
cin>>s;
int len=strlen(s);
int sum=0;
for(int i=0;i<len;i++){
f[i][i]=0;//若只有一个字符,则它为回文字符串。
}
for(int k=1;k<len;k++){//枚举头尾间距
for(int l=0;l<len-k;l++){//枚举起点
int r=l+k;
if(s[l]==s[r]){
f[l][r]=f[l+1][r-1];
}else{
f[l][r]=min(f[l+1][r],f[l][r-1])+1;
}
}
}
cout<<f[0][len-1]<<endl;
return 0;
}