• 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;
    }
  • 相关阅读:
    名称空间与作用域
    3.19作业
    函数的参数
    文件的f.seek和文件修改方式以及函数的基本使用
    3.17作业
    文件处理
    3.16作业
    转 移动端-webkit-user-select:none导致input/textarea输入框无法输入
    移动端开发兼容性总结
    移动端input 无法获取焦点的问题
  • 原文地址:https://www.cnblogs.com/sugewud/p/9918342.html
Copyright © 2020-2023  润新知