Description
现在有n堆石子,第i堆有ai个石子。现在要把这些石子合并成一堆,每次只能合并相邻两个,每次合并的代价是两堆石子的总石子数。求合并所有石子的最小代价。
Input
第一行包含一个整数T(T<=50),表示数据组数。
每组数据第一行包含一个整数n(2<=n<=100),表示石子的堆数。
第二行包含n个正整数ai(ai<=100),表示每堆石子的石子数。
Output
每组数据仅一行,表示最小合并代价。
Sample Input
2
4
1 2 3 4
5
3 5 2 1 4
Sample Output
19
33
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int n=200;
int sto[n];
int dp[n][n];//dp[i][j]表示从i到j的最优解
int sum[n];
int main()
{
int T;
int n;
int i,j,k,len;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
sum[0]=0;
for(i=1;i<=n;i++)
{
scanf("%d",&sto[i]);
sum[i]=sum[i-1]+sto[i];
}
memset(dp,0,sizeof(dp));
for(len=2;len<=n;len++)//长度
{
for(i=1;i<=n-len+1;i++)//起始点
{
j=i+len-1;
dp[i][j]=10000000;//dp[i][j]表示从i到j的最优解
for(k=i;k<j;k++)//中间点
{
//每次合并的代价是两堆石子的总石子数
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
}
}
}
printf("%d\n",dp[1][n]);
}
return 0;
}