数字三角形 【暴搜 + 记忆化 + DP】

😊😊 😊😊
不求点赞,只求耐心看完,指出您的疑惑和写的不好的地方,谢谢您。本人会及时更正感谢。希望看完后能帮助您理解算法的本质
😊😊 😊😊

题目描述:

给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。
在这里插入图片描述
Input

输入的是一行是一个整数N (1 < N <= 100),给出三角形的行数。下面的N行给出数字三角形。数字三角形上的数的范围都在0和100之间。

Output

输出最大的和。

Sample Input

5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

Sample Output

30

小白到进阶各种解法:

一、暴搜:😊

在这里插入图片描述

代码:

写法一:

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 5e2 + 10;
int f[N][N];    //表示矩阵
int n;
int res;

void dfs (int x, int y, int cost)
{
    if (x == n)
    {
        res = max(res, cost);
        return ;
    }
    
    dfs (x+1, y, cost + f[x+1][y]);
    dfs (x+1, y+1, cost+f[x+1][y+1]);
}

int main()
{
    cin >> n;
    for (int i=1; i <= n; i ++)
        for (int j=1; j <= i; j ++)
            cin >> f[i][j];
            
    dfs(1, 1, f[1][1]);
    cout << res << endl;        
    return 0;
}

写法二:

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 5e2 + 10;
int f[N][N];    //表示矩阵
int n;

int dfs (int x, int y)
{
    if (x == n)
        return f[x][y];
    int res=f[x][y];  //记录从当前状态到目的状态的最优答案
    res += max(dfs (x+1, y), dfs (x+1, y+1));
    
    return res;
}

int main()
{
    cin >> n;
    for (int i=1; i <= n; i ++)
        for (int j=1; j <= i; j ++)
            cin >> f[i][j];
    cout << dfs(1, 1) << endl;        
    return 0;
}

在这里插入图片描述

二、记忆化搜索:😊

在这里插入图片描述

代码:

被卡了一个数据!

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 5e2 + 10, inf = 11010;
int mm[N][N];
int g[N][N];
int n;

int dfs (int x, int y)
{
    if (mm[x][y])
        return mm[x][y];
    if (x == n){
        mm[x][y] = g[x][y];
        return mm[x][y];
    }
    int res=0;
    res += max(dfs(x+1, y), dfs(x+1, y+1)) + g[x][y];
    mm[x][y] = res;
    return res;
}

int main()
{
    cin >> n;
    for (int i=1; i <= n; i ++)
        for (int j=1; j <= i; j ++)
            cin >> g[i][j];
    cout << dfs (1, 1);
    return 0;
}

还是被卡了一个数据:

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 5e2 + 10, inf = 11010;
int mm[N][N];
int g[N][N];
int n;

int dfs (int x, int y)
{
    if (mm[x][y])
        return mm[x][y];
    if (x == n){
        mm[x][y] = g[x][y];
        return mm[x][y];
    }
    mm[x][y] += max(dfs(x+1, y), dfs(x+1, y+1)) + g[x][y];
    return mm[x][y];
}

int main()
{
    cin >> n;
    for (int i=1; i <= n; i ++)
        for (int j=1; j <= i; j ++)
            cin >> g[i][j];
    cout << dfs (1, 1);
    return 0;
}

在这里插入图片描述

三、本题考察算法:动态规划😊

代码:

正推写法:
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 5e2 + 10, inf = 0x3f3f3f3f;
int g[N][N];
int f[N][N];
int n;

int main()
{
    scanf("%d", &n);
    int a;
    for (int i=1; i <= n; i ++)
        for (int j = 1; j <= i; j ++ )
        {
            cin >> g[i][j];
        }
    memset (f, -inf, sizeof(f));
    f[1][1] = g[1][1];
    for (int i=2; i <= n; i ++) 
    {
        for (int j=1; j <= i; j ++)
        {
            f[i][j] = max(f[i-1][j], f[i-1][j-1]) + g[i][j];
        }
    }
    int res=-inf;
    for (int i=1; i <= n; i ++)
        res = max(res, f[n][i]);
    cout << res;
    return 0;
}
倒推写法:无需初始化
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 5e2 + 10, inf = 11010;
int f[N][N];
int g[N][N];
int n;

int main()
{
    cin >> n;
    for (int i=1; i <= n; i ++)
        for (int j=1; j <= i; j ++)
            cin >> g[i][j];

    for (int i=n; i >= 1; i--){
        for (int j=1; j <= i; j ++){
            f[i][j] = max(f[i+1][j], f[i+1][j+1]) + g[i][j];
        }
    }
    cout << f[1][1];
    return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值