将n堆合并问题化为子问题n-1,n-2 , .... , 2
dp[i][j]代表从i堆石子到j堆石子合并的最小代价
那么dp[1][n]就是答案、
状态转移方程 dp[i][j]=min(dp[i][j], dp[i][k]+dp[k+1][j]+sum[i][j]) i<=k<=j
因为只能相邻的两个才能合并、
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
typedef long long ll;
const int qq = 1005;
const int INF = 1e9 + 10;
struct cmp{
bool operator () (int &a, int &b){
return a>b;
}
};
ll sum[qq];
ll dp[qq][qq];
int main(){
int n;scanf("%d",&n);
ll x;
for(int i=1; i<=n; ++i){
scanf("%lld",&x);
sum[i] = sum[i-1] + x;
}
for(int len=2; len<=n; ++len){
for(int i=1; i<=n; ++i){
int j=len+i-1;
dp[i][j]=INF;
for(int 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("%lld\n", dp[1][n]);
return 0;
}