美团笔试题——最优二叉树II

题目描述

小团有一个由N个节点组成的二叉树,每个节点有一个权值。定义二叉树每条边的开销为其两端节点权值的乘积,二叉树的总开销即每条边的开销之和。小团按照二叉树的中序遍历依次记录下每个节点的权值,即他记录下了N个数,第i个数表示位于中序遍历第i个位置的节点的权值。之后由于某种原因,小团遗忘了二叉树的具体结构。在所有可能的二叉树中,总开销最小的二叉树被称为最优二叉树。现在,小团请小美求出最优二叉树的总开销。

输入描述:

第一行输入一个整数N(1<=N<=300),表示二叉树的节点数。
第二行输入N个由空格隔开的整数,表示按中序遍历记录下的各个节点的权值,所有权值均为不超过1000的正整数。

输出描述:

输出一个整数,表示最优二叉树的总开销。

输入例子1:

5
7 6 5 1 3

输出例子1:

45

题解
记忆化搜索
枚举每个a[i]为当前的根节点,搜索a[i]左边为左子节点,a[i]右边为右子节点,计算最大值

#include<bits/stdc++.h>
using namespace std;
const int N = 300 + 10;
int a[N];
int d[N][N][N];
int dfs(int l, int r, int p)
{
    if(l > r) return 0;
    if(d[l][r][p] != -1) return d[l][r][p];
    int res = 1e9 ;
    for(int i = l; i <= r; i++){
        int left = dfs(l,i-1,i);
        int right = dfs(i + 1,r,i);
        res = min(res,left + right + a[p]*a[i]);
    }
    d[l][r][p] = res;
    return d[l][r][p];
}
int main()
{
    int n;
    cin >> n;
    memset(d,-1,sizeof d);
    for(int i = 1; i <= n; i++){
        cin >> a[i];
    }
    cout << dfs(1,n,0) << endl;
    return 0;
}

相关推荐
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页