返回题解分享
讨论 / 题解分享/ 帖子详情

数字三角形(编程题) - 题解

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 110;

int f[N][N][N];
int a[N][N];
int n;
int main(){

    cin >> n;

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

    for(int i = 1;i <= n;i++)f[n][i][0] = a[n][i];

    //f[i][j][k]----->表示到i,j,向左下走k次。
    for(int i = n-1;i >= 1;i--){
        for(int j = 1;j <= i;j++){
            for(int k = 0;k <= n-i;k++){
                f[i][j][k] = f[i+1][j+1][k]+a[i][j];//从右下来的,则左下走k次,k与下一层是一样的
                if(k >= 1){//当下一层的往左下的次数是大于1,此时才可能是从左下来的,因为要减去1
                    f[i][j][k] = max(f[i][j][k],f[i+1][j][k-1] + a[i][j]);
                }
            }
        }
    }

    if(n % 2 == 1){//n是奇数,则移动次数n-1位偶数,则一定是对半分的次数
        cout << f[1][1][(n-1)/2];
    }
    else{//n是偶数,移动次数n-1是奇数,则可能是1-0,也可能0-1组合
        cout << max(f[1][1][(n-1)/2],f[1][1][(n-1)/2+1]);
    }
    return 0;
}
`
2 回复 0 转发 0 喜欢 6 阅读
回复 (2)
默认 最新
露米 4 天前
看到你分享的题解了,思路很扎实。

在经典数字三角形的基础上,通过增加维度 k 来精准控制向左走的次数,从而满足“左右步数差不超过 1”的限制,这个切入点找得很准。代码整体逻辑非常清晰,尤其是最后对 $n$ 奇偶性的分类讨论,处理得也很细致。

如果能稍微补充一下关于状态转移方程 f[i][j][k] 的具体思考过程,相信对其他正在学习动态规划的小伙伴会更有启发。另外
在实现这种三维 DP 的过程中,有没有遇到过让你觉得比较棘手的小细节呢?🙂
比如在处理边界判断,或者在思考如何进一步优化空间复杂度的时候?这道题确实很考验细心程度。

慢慢来,期待以后能看到你更多有趣的思路分享。
0
露米 2026/2/11
看到你分享的题解了,思路很扎实。

通过增加一个维度 k 来记录向左下走的次数,从而巧妙地解决了路径平衡的限制,这个切入点找得很准。这种自底向上的写法在最后处理奇偶数判断时,逻辑也显得非常清晰。

如果能稍微补充一下关于状态转移方程 f[i][j][k] 的具体思考过程,相信对其他正在学习动态规划的小伙伴会更有启发。另外,在实现这种三维 DP 的过程中,有没有遇到过让你觉得比较棘手的小细节呢?🙂
比如在处理边界判断,或者在思考如何平衡空间复杂度的时候?这道题确实很考验细心程度。

慢慢来,期待以后能看到你更多有趣的思路分享。
0