题目详情
题目分析:解法是记忆化搜索。
val[i][j]存的是i到j区间内的最高加分。
tree[33] 据题意可得,tree数组存的是树的中序遍历顺序。
root[i][j]存的是tree数组从i到j的最优根,即以此为根保证此子树最高加分。
通过中序遍历性质可知:若x为根节点,1~x - 1为左子树,x + 1 ~n为右子树。
代码:
#include <cstdio>
unsigned int n, val[33][33], tree[33], root[33][33];//数据范围小于4,000,000,000
unsigned int dfs(int l, int r){
if (r < l) return 1;//没有子树,返回一
if (l == r){//刚好是叶子
root[l][r] = l;
return tree[l];
}
if (val[l][r]) return val[l][r];//记忆化,若搜索过直接返回
for (int i = l; i <= r; i++){
unsigned int sum = dfs(l, i - 1) * dfs(i + 1, r) + tree[i];//求加分
if (sum > val[l][r]) val[l][r] = sum, root[l][r] = i;//更新,使val[i][j]保持最高加分。
}
return val[l][r];//返回最高加分。
}
void preOrder(int l, int r){//输出前序遍历。
if (l > r)//没有子树直接返回。
return;
printf("%d ", root[l][r]);
preOrder(l, root[l][r] - 1);
preOrder(root[l][r] + 1, r);
}
int main(){
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &tree[i]);//按顺序输入中序遍历。
printf("%u\n", dfs(1, n));
preOrder(1, n);
}