C++ 洛谷 P216 数字三角形 三种解法:dfs, 动态规划(顺推,逆推)

文章展示了C++实现的深度优先搜索(DFS)和记忆化搜索在解决矩阵问题上的应用,并对比了未优化的DFS与记忆化搜索。同时,介绍了动态规划的顺推和逆推方法,通过从底部向上累加和从顶部向下累加来优化问题求解。这些技术揭示了动态规划思想的发展过程,从暴力递归到剪枝优化,再到高效的状态转移策略。
摘要由CSDN通过智能技术生成

C++代码 dfs 搜素和优化后的记忆化搜素

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int maxn = 1001;
int r, a[maxn][maxn], f[maxn][maxn];

int dfs0(int x, int y) // 提交超时
{   
    if(x==r-1)
    {
        return a[x][y];
    }
    return max(dfs0(x+1, y), dfs0(x+1, y+1))+a[x][y];
}

int dfs(int x, int y) // 记忆化搜索 x为行,y为列
{
    if (f[x][y] >= 0)
        return f[x][y]; // 如果这个数算过就直接返回,不用再一次计算
    if (x == r-1)
        f[x][y] = a[x][y]; // 如果到了最后一行,就直接赋值,因为没有下一行无法判断
    else
        f[x][y] = max(dfs(x + 1, y), dfs(x + 1, y + 1)) + a[x][y]; // 把下一行较大的数与这一个数相加
    return f[x][y];
}

int main()
{
    scanf("%d", &r);
    for (int i = 0; i < r; i++)
        for (int j = 0; j <= i; j++)
            scanf("%d", &a[i][j]);


    // int ans = dfs0(0, 0);
    // std::cout << ans << std::endl;
    memset(f, -1, sizeof(f));  // 此处把f全都定义成-1,是因为金字塔里面的数有可能也是0,这样就更容易判断
    cout << dfs(0, 0) << endl;
    return 0;
}

c++ 代码:顺推, 逆推, 实际就是动态规划

#include <iostream>
#include <cstring>
using namespace std;

const int maxn = 1001;
int r, a[maxn][maxn];

int shuntui()
{
    int ans = 0;
    int x, y;
    for (x = 1; x < r; x++) // 向下逐层累加
        for (y = 0; y <= x; y++){
            if (y == 0)
                a[x][y] += a[x - 1][y];
            else
                a[x][y] += max(a[x - 1][y - 1], a[x - 1][y]);
        }
                
    for (x = 0; x < r; x++) // 最后一行找出最大值
        ans = max(ans, a[r-1][x]);
    return ans;
}

int nitui()
{
    int x, y;
    for (x = r-2; x >= 0; x--) // 向上逐层累加
        for (y = 0; y <= x; y++)
            a[x][y] += max(a[x+1][y],a[x+1][y+1]);

    return a[0][0];
}

int main()
{
    scanf("%d", &r);
    for (int i = 0; i < r; i++)
        for (int j = 0; j <= i; j++)
            scanf("%d", &a[i][j]);
    cout << nitui() << endl;
    return 0;
}

总结: 依次思索这个几种解法可以了解动态规划思想的产生过程,先是暴力递归,再是记忆化递归(相当于大量剪枝递归树),然后是动态规划,从顺推到逆推,就是为了更好的动态规划。

参考链接:

[1]数字金字塔(逆推法)——信息学竞赛培训课程

[2]动态规划详解(修订版)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值