入门——动态规划2

点击查看代码
/*
动态规划

第一种:通过记忆化搜素(先用递归的思想去解决问题;如果有重复子问题,就改成用记忆化搜索的形式)

(其实递推形式的动态规划中的各种表述,是可以对应到递归形式的:
• 状态表⽰ <---> 递归函数的意义;
• 状态转移⽅程 <---> 递归函数的主函数体;
• 初始化 <---> 递归函数的递归出⼝。)


第二种:直接使用递推形式的动态规划解决:
1.定义状态表示:
        一般情况下根据经验+递归函数的意义,赋予dp数组相应的含义
2.推导状态转移方程:
        根据状态表示以及题意,在dp表中分析,当前格子如何通过其余各自推导出来
3.初始化:
        根据题意,先将显而易见的以及边界情况下的位置填上值
4.确定填表顺序:
        根据状态转移方程,确定按照什么顺序来填表
5.确定最终结果
        根据题意,在表中找出最终结果
*/


/*
题目:数字三角形

1.状态表示
        根据题目要求
        f[i][j]表示:从[1, 1] 走到 [i, j]位置时,所有方案下的最大权值

2.状态转移方程
        根据“最后一步”划分情况
        f[i][j] = max(f[i - 1][j - 1], f[i - 1][j]) + a[i][j]

3.初始化!!!
        1.填表的时候不越界
        2.保证后面的填表是正确的

    思考:如果权值出现负数怎么办?
            memset(f, -0x3f3f3f, sizeof(f)),f[0][0] = f[0][1] = 0

4.填表顺序
        仅需保证从上到下就足矣

5.最终结果
        最后一行的最大值

6.优化:空间优化
            二维 -> 两个一维数组(一个表示当前需要计算的权值,另一个表示上次计算的权值) -> 一个一维数组
            f[j] = max(f[j-1], f[j]) + a[i][j]
        填表顺序:从左到右
 
        总结:
        二维转一维:
            1.是否修改遍历顺序
            2.删掉第一维即可

*/

//https://www.luogu.com.cn/problem/P1216

#include <iostream>
#include <cstring> // 用于memset函数

using namespace std;

const int N = 1010;
int a[N][N];          // 存储数字三角形的原始数值
//int f[N][N];          // dp表,f[i][j]表示从(1,1)到(i,j)的最大权值
int f[N];   //空间优化,二维 -> 一维

int main() {
    int r;
    cin >> r;
    
    // 1. 输入数字三角形(从1,1开始存储,方便处理边界)
    for (int i = 1; i <= r; i++) {
        for (int j = 1; j <= i; j++) {
            cin >> a[i][j];
        }
    }


    // // 3. 填表(状态转移)
    // // 填表顺序:从上到下,从左到右
    // for (int i = 1; i <= r; i++) { 
    //     for (int j = 1; j <= i; j++) {
    //         // 状态转移方程:当前位置的最大权值 = 上一行两个可能位置的最大值 + 当前值
    //         // 注意边界:j=1时只能从j=1来,j=i时只能从j=i-1来
    //         f[i][j] = max(f[i - 1][j - 1], f[i - 1][j]) + a[i][j];
    //     }
    // }

    for(int i = 1; i <= r; i++){
        for(int j = i; j >= 1; j--){    //要注意顺序,从左到右,不然会改变每一次的结果
            f[j] = max(f[j - 1],f[j]) + a[i][j];  //当前f[j] 和左边 f[j - 1] 的max
        }
    }
    // // 4. 找最终结果:最后一行的最大值
    int ret = 0;
    // for (int j = 1; j <= r; j++) {
    //     ret = max(ret, f[r][j]);
    // }
    for(int j = 1; j <= r; j++){
        ret = max(ret, f[j]);
    }
    cout << ret << endl;
    return 0;
}
posted @ 2026-03-10 22:17  无酒无剑  阅读(20)  评论(0)    收藏  举报