还是建立不起来自己的动归意识啊。。。。
输入的数据是有序递增的,所以省去了排序的步骤。
思路:对每个区间选出一个点当作根节点。。。而区间上除了根节点左右最优解要多加一个高度,
状态:dp[i][j]表示a[i]到a[j]所构成的二叉树的最小代价。
状态转移:dp[i][j] = min(dp[i][k-1]+dp[k+1][j]+sum[j]-sum[i-1]-a[k]); {i<k<j;}
代码如下:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define M 300 #define INF 0x7fffffff int n, a[M], dp[M][M], sum[M]; int main () { sum[0] = 0; while(~scanf("%d",&n)) { for(int i = 1; i <= n; i++) { scanf("%d",&a[i]); sum[i] = sum[i-1]+a[i]; dp[i][i] = 0; } for(int len = 1; len < n; len++) for(int i = 1, j = i+len; j <= n+1; i++,j++) { dp[i][j] = INF; dp[i][j] = min(dp[i][j],dp[i+1][j]+sum[j]-sum[i-1]-a[i]); dp[i][j] = min(dp[i][j],dp[i][j-1]+sum[j]-sum[i-1]-a[j]); for(int k = i+1; k <= j-1; k++) { dp[i][j] = min(dp[i][j],dp[i][k-1]+dp[k+1][j]+sum[j]-sum[i-1]-a[k]); } } printf("%d\n",dp[1][n]); } return 0; }