根据题意由于石子的合并有很多种方法,要我们找到所需要代价最小的方法
石子合并只能与相邻的堆进行合并
很多堆石子它们的最终宿命不过合成一堆,那么在合成一堆前它肯定是分成左右两堆了的
个人感觉这里有点类似分而治之的感觉(不太确定)
我们用f[i][j]表示合并i号到j号石块的方法集合、它的属性是min
如何划分这个集合呢
我们枚举所有的长度
我们需要找到一个分解点把f[i][j]这一堆划分为两堆也就是f[i][j]=f[i][k]+f[k+1][j]
当然最后我们合成的时候加上i到j的总价值 这里我们可以用前缀和的思维写
#include<iostream>
using namespace std;
const int N=310;
int f[N][N];//f[i][j]表示的是从把i堆石子到j堆石子合并的操作集合,属性为min
int w[N];
int n;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%d",&w[i]);
w[i]+=w[i-1];//预处理前缀和
}
for(int len=2;len<=n;len++)//枚举所有长度
for(int i=1;i+len-1<=n;i++)//枚举所有的起点
{
int j=i+len-1;//j是终点
f[i][j]=1e9;
for(int k=i;k<j;k++)//寻找划分点
{
f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+w[j]-w[i-1]);
}
}
cout<<f[1][n]<<endl;
return 0;
}