思路
與傳統的哈夫曼編碼不同,本題的編碼只能是相鄰的進行構造。我們發現每一個字母的編碼的長度相當於在一顆編碼樹中的深度。我們回想一下,石子合併,在石子合併過程中,每個數被合併的次數就相當於一個字母的編碼長度在一顆編碼樹中的深度,而每堆石子的數量就相當於字母出現的頻率數,因此,這道題的本質就是一道裸的區間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;
}