记忆化搜索

记忆化搜索 也是搜索的一种,实则以空间换时间。当然多花一点空间 可以换来时间上的巨大提升。往往就从超时直到接过了。再说都2020年了 内存都是以G为单位的,可以说以一点空间换时间的缩短,可以说是很值得的。

好了,不扯废话了,上两道题意思意思
题面
设一个 n n n个节点的二叉树tree的中序遍历为 ( 1 , 2 , 3 , … , n ) (1,2,3,…,n) 1,2,3,,n,其中数字 1 , 2 , 3 , … , n 1,2,3,…,n 1,2,3,,n为节点编号。每个节点都有一个分数(均为正整数),记第ii个节点的分数为di, tree及它的每个子树都有一个加分,任一棵子树subtree(也包含treetree本身)的加分计算方法如下:
subtree的左子树的加分× subtree的右子树的加分+subtree的根的分数。
若某个子树为空,规定其加分为1,叶子的加分就是叶节点本身的分数。不考虑它的空子树。
试求一棵符合中序遍历为 ( 1 , 2 , 3 , … , n ) (1,2,3,…,n) 1,2,3,,n且加分最高的二叉树tree。要求输出:
(1)treetree的最高加分
(2)treetree的前序遍历

思路
中序遍历就是先访问左子树,再访问根节点,最后访问右节点(左,中,右);
这道题。
既然要求最高得分,那就是求左子树x右子树+根节点的分数
一开始 我是肤浅的认为 要求分数最高 那就把左右子树弄得大些,因为它两相乘嘛。所以把最小的放为根节点。但是我忽略了一个重要因素 那就是它不一定都有两个叶节点的。如果只有一个叶节点 那就只能乘一。最致命的如果给出的数据像这样
5
5 7 8 18 19 那它就是一条长链 总分就是19+18+8+7+5.
所以不能这样算。
中序遍历是1,2,3,4,…n 题目要求的是求左子树x右子树+根节点的分数
那我是不是 只要知道根节点是第几位就行了。总共n个数,到底哪个才是根节点呢,实在不行,我就一个一个的枚举。用一个for循环 然后求得最大值。

//求区间L,R之间的最大分数
long long dfs(int L,int R){
    //最大值 要定义在函数内
    //如果定义在全局变量的话,那就不是L R之间的最大值,就是全局的最大值
    long long maxn=0;
    //递归边界条件
    if(L>R) return 1;
    if(L==R) return a[L];
    if(m[L][R]) return m[L][R];
    //递归思想 枚举这个L到R的区间内的每个数,分别作为根节点 求最大值
    for(int i=L;i<=R;i++){
  
        long long tmp=dfs(L,i-1)*dfs(i+1,R)+a[i];// 选定一个根节点 分别去找它左区间和有区间的最大值
        
        if(tmp>maxn){
        root[L][R]=i;
        maxn=tmp;
        }
    }
    //把这个区间里的最大值存起来
    m[L][R]=maxn;
    
    //cout<<"区间"<<L<<" "<<R<<"根节点"<<root[L][R]<<"  最大值"<<maxn<<endl;

    //遍历结束 返回这个区间的最大值
    return maxn;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值