思路
与传统的哈夫曼编码不同,本题的编码只能是相邻的进行构造。我们发现每一个字母的编码的长度相当于在一颗编码树中的深度。我们回想一下,石子合并,在石子合并过程中,每个数被合并的次数就相当于一个字母的编码长度在一颗编码树中的深度,而每堆石子的数量就相当于字母出现的频率数,因此,这道题的本质就是一道裸的区间DP。
AC代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e3 + 5;
int a[maxn];
int sum[maxn];
int dp[maxn][maxn];
int main(void) {
int n;
cin >> n;
for(int i = 1; i <= n; i++){
cin >> a[i];
sum[i] += sum[i-1]+a[i];
}
for(int len = 2; len <= n; len++){ //枚举区间长度
for(int i = 1; i+len-1<=n; i++){
int j = i+len-1; //i是区间起点,j是区间终点
dp[i][j] = 0x3f3f3f3f;
for(int k = i; k <= j; k++){
dp[i][j] = min(dp[i][j],dp[i][k-1]+dp[k][j]+sum[j]-sum[i-1]);
}
}
}
cout<<dp[1][n]<<endl;
return 0;
}