zoukankan      html  css  js  c++  java
  • P1040 加分二叉树(树上记忆化搜素)

    这道题很水

    但我没做出来………………………………

    我写的时候状态设计错了,设计dp[l][m][r]为从l到r以m为根的值

    这样写遍历状态就是n^3的,会TLE。

    而且写路径的时候是用结构体写的,这样会错,应该用root[l][r]表示从l到r的根

    对于l到r,枚举根在哪就好了

    总结

    (1)状态设计,学会简洁的设计状态

    (2)路径输出,可以开和dp数组一样的数组,在dp数组更新的时候路径数组也更新

    (3)在非线性结构上做dp的时候(如树),用记忆化搜索会比递推方便。

    #include<bits/stdc++.h>
    #define REP(i, a, b) for(register int i = (a); i < (b); i++) 
    #define _for(i, a, b) for(register int i = (a); i <= (b); i++) 
    using namespace std;
    
    const int MAXN = 50;
    int a[MAXN], ans, dp[MAXN][MAXN];
    int n, root[MAXN][MAXN];
    
    int dfs(int l, int r)
    {
        if(l > r) return 1;
        if(dp[l][r] != -1) return dp[l][r];
        if(l == r) //注意叶子的情况可能要特判 
        {
            root[l][r] = l;
            return dp[l][r] = a[l];
        }
        
        int res = 0; 
        _for(m, l, r)
        {
            int val = dfs(l, m - 1) * dfs(m + 1, r) + a[m];
            if(val > res) res = val, root[l][r] = m;
        }
        
        return dp[l][r] = res;
    }
    
    void print(int l, int r)
    {
        if(l > r) return;
        printf("%d ", root[l][r]);
        print(l, root[l][r] - 1);
        print(root[l][r] + 1, r);
    }
    
    int main()
    {
        scanf("%d", &n); 
        memset(dp, -1, sizeof(dp));
        _for(i, 1, n) scanf("%d", &a[i]);
        printf("%d
    ", dfs(1, n));
        print(1, n);
        return 0;
    }
  • 相关阅读:
    html中的a标签
    dl,dt,dd标签的使用
    MySQL innodb中各种SQL语句加锁分析
    Js字符串与十六进制的相互转换 【转】
    亿级Web系统搭建:单机到分布式集群【转】
    pm2 设置开机启动
    spring cloud 项目相关集成简介
    spring boot下JedisCluster方式连接Redis集群的配置
    并发编程 – Concurrent 用户指南--转
    JDBC 事务和 JTA 事务
  • 原文地址:https://www.cnblogs.com/sugewud/p/9918342.html
Copyright © 2011-2022 走看看