题意:给n个符号建立一棵排序二叉树,给出每个符号检索的频率,要求从检索的次数最小。
分析:《训练指南》P64。
参考:https://blog.csdn.net/count24/article/details/7226640
代码:
#include<bits/stdc++.h>
#define INF 16843009
#define IM 253
#define FU(i,a,b) for (int _n(b), i(a); i < _n; i++)
#define FD(i,a,b) for(int i=(a),_b=(b);i>=_b;--i)
#define CL(a,v) memset((a),(v),sizeof(a))
using namespace std;
int n;
int sum[IM];
int w[IM][IM];
int dp[IM][IM];
int s[IM][IM];
void Init(){
int t;
sum[0] = 0;
FU(i,1,n+1){
cin>>t;
sum[i] = sum[i-1] + t;
}
FU(i,0,n+1)
FU(j,i,n+1)
w[i][j] = sum[j] - sum[i-1];
CL(dp,1);
}
int DP(){
FU(i,0,IM) dp[i][i] = 0,s[i][i] = i;
FU(len,2,n+1){
FU(i,1,n+4){
int j = i + len - 1;
if(j > n+2) break; // index !!!
FU(k,s[i][j-1],s[i+1][j]+1){
if(i > k-1) dp[i][k-1] = w[i][k-1] = 0;
if(k+1 > j) w[k+1][j] = dp[k+1][j] = 0;
int tmp = dp[i][k-1]+dp[k+1][j]+w[i][k-1]+w[k+1][j];
if(tmp < dp[i][j]){
dp[i][j] = tmp;
s[i][j] = k;
}
}
}
}
return dp[1][n];
}
int main(){
while(cin>>n){
Init();
cout<<DP()<<endl;
}
return 0;
}