• 数字三角形模型相关题目



    数字三角形模型dp可以叫做路径dp。

    摘花生

    摘花生

    这是一道路径dp的裸题。
    做路径dp时注意初始化的问题。由于这里求的是max,因此不用初始化也可以。
    ac代码:

    #include 
    
    using namespace std;
    
    int n;
    
    int row, col;
    
    const int N = 1010;
    
    int g[N][N], f[N][N];
    
    int main()
    {
        cin >> n;
        for(int i = 0; i < n; i++)
        {
            cin >> row >> col;
            for(int i = 1; i <= row; i++)
                for(int j = 1; j <= col; j++)
                    cin >> g[i][j];
            
            for(int i = 1; i <= row; i++)
                for(int j = 1; j <= col; j++)
                    f[i][j] = max(f[i - 1][j], f[i][j - 1]) + g[i][j];
                    
            cout << f[row][col] << endl;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    最低通行费

    最低通行费
    这也是路径dp的裸题。
    由于这里求的是min,因此初始化的时候要注意,当i等于1和j等于1的情况,由于边界是0值,因此不能直接取min。

    ac代码

    #include 
    
    using namespace std;
    
    int n;
    
    const int N = 110;
    
    int g[N][N], f[N][N];
    
    int main()
    {
        cin >> n;
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                cin >> g[i][j];
        
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
            {
                if(i == 1) f[i][j] = f[i][j - 1] + g[i][j];
                else if(j == 1) f[i][j] = f[i - 1][j] + g[i][j];
                else f[i][j] = min(f[i - 1][j], f[i][j - 1]) + g[i][j];
            }
        
        cout << f[n][n];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    方格取数

    方格取数
    裸题是一次走一条路径,这题是一次走两条路径,维度加深,也可以当作一道经典的模板题来学习。

    基本思路:两条路径是同时走的,因此每次有4个方向可以选择。因此集合可以被划分成四份。
    当两条路径走到相同的一个点的时候,由题意知只能加一次的值,因此每当坐标相等的时候,只加一份的值。

    ac代码:

    #include 
    
    using namespace std;
    
    const int N = 20;
    
    int g[N][N], f[N][N][N][N];
    
    int n;
    
    int main()
    {
        cin >> n;
        int x, y, num;
        while(cin >> x >> y >> num, x , y, num) g[x][y] = num;
        
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                for(int k = 1; k <= n; k++)
                    for(int l = 1; l <= n; l++)
                    {
                        int x;
                        if(i == k && j == l) x = g[i][j];
                        else x = g[i][j] + g[k][l];
                        int& cur = f[i][j][k][l];
                        cur = max(cur, f[i - 1][j][k - 1][l] + x);
                        cur = max(cur, f[i - 1][j][k][l - 1] + x);
                        cur = max(cur, f[i][j - 1][k - 1][l] + x);
                        cur = max(cur, f[i][j - 1][k][l - 1] + x);
                    }
                    
        cout << f[n][n][n][n];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    传纸条

    传纸条
    这道题是方格取数的变形题。方格取数是两个路径走过同一个点只能加一次值。传纸条是两个路径不能走过同一个点。其实本质是一样的。详细看证明:
    为什么走过同一个点只加一次值等价于不能走同一个点

    简易说明:最优解一定可以被替换成两条路径完全没有交点的情况。而完全没有交点的最大值也就是两个路径走过同一个点只能加一次值的最大值。

    总结:在没有负数的情况下,两条路径没有交点,两条路径走过同一个点只能加一次值,两条路径不能走同一个点是等价的。

    ac代码:

    #include 
    
    using namespace std;
    
    const int N = 60;
    
    int g[N][N], f[N][N][N][N];
    
    int n, m;
    
    int main()
    {
        cin >> n >> m;
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)
                cin >> g[i][j];
        
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)
                for(int k = 1; k <= n; k++)
                    for(int l = 1; l <= m; l++)
                    {
                        int x;
                        if(i == k && j == l) x = g[i][j];
                        else x = g[i][j] + g[k][l];
                        int& cur = f[i][j][k][l];
                        cur = max(cur, f[i - 1][j][k - 1][l] + x);
                        cur = max(cur, f[i - 1][j][k][l - 1] + x);
                        cur = max(cur, f[i][j - 1][k - 1][l] + x);
                        cur = max(cur, f[i][j - 1][k][l - 1] + x);
                    }
                    
        cout << f[n][m][n][m];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
  • 相关阅读:
    中小企业选择ERP系统时应关注的10个关键功能
    金融期货和期权等品种权限
    嵌入式分享合集83
    C++总结(8):STL容器适配器之stack、queue、priority_queue详解
    力扣(LeetCode)1668. 最大重复子字符串(C++)
    Java——逻辑控制1
    PySide6实现word转化pdf
    jsp+ssm+maven大学生就业信息系统
    为什么 Intent 不能传递大数据
    【python算法基础】回溯算法
  • 原文地址:https://blog.csdn.net/m0_51641706/article/details/126511802