zoukankan      html  css  js  c++  java
  • 数字三角形

    一、问题描述

    给出一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上的数加起来可以得到一个和,和最大的路径称为最佳路径。你的任务是求出最佳路径上的数字之和。注意:路径上的每一步只能从一个数走到下一层上和它最近的左边或者右边的数。

    二、输入数据

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

    三、输出要求

    输出最大的和

    四、输入样例

    5

    7

    3 8

    8 1 0

    2 7 4 4

    4 5 2 6 5

    五、输出样例

    30

    六、解题思路

    这道题可以用递归的方法解决。以D(r,j)表示第r行第j个数字,以MaxSum(r,j)表示从第r行的第j个数字到底边的最佳路径的数字之和,则本题是要求MaxSum(1,1)。

    从某个D(r,j)出发,显然下一步只能走D(r+1,j)或者D(r+1,j+1)。如果走D(r+1,j)。那么得到的MaxSum(r,j)就是MaxSum(r+1,j)+D(r,j);如果走D(r+1,j+1),那么得到的MaxSum(r,j)就是MaxSum(r+1,j+1)+D(r,j)。所以,选择往哪里走,就看MaxSum(r+1,j)那个更大。为了提高效率,可以用一个二维数组aMaxSum[N][N]来存放计算出来的MaxSum值,下次需要MaxSum的值时直接取对应aMaxSum的值即可,避免重复计算。

    #include<stdio.h>
    #include<memory.h>
    #define MAX_NUM 100
    int D[MAX_NUM + 10][MAX_NUM + 10];
    int N;
    int aMaxSum[MAX_NUM + 10][MAX_NUM + 10];
    int MaxSum(int r, int j) {
        if(r == N)
            return D[r][j];
        if(aMaxSum[r + 1][j] == -1)
            aMaxSum[r + 1][j] = MaxSum(r + 1, j);
        if(aMaxSum[r + 1][j + 1] == -1)
            aMaxSum[r + 1][j + 1] = MaxSum(r + 1, j + 1);
        if(aMaxSum[r + 1][j] > aMaxSum[r + 1][j + 1])
            return aMaxSum[r + 1][j] + D[r][j];
        return aMaxSum[r + 1][j + 1] + D[r][j];
    }
    
    int main()
    {
        int m;
        scanf("%d", &N);
        memset(aMaxSum, -1, sizeof(aMaxSum));
        for(int i = 0; i <= N; i++) {
            for(int j = 1; j <= i; j++) {
                scanf("%d", &D[i][j]);
            }
        }
        printf("%d", MaxSum(1, 1));
        return 0;
    }
    

    这种讲一个问题分解为子问题递归求解,并且将中间结果保存避免重复计算的办法就叫做动态规划。动态规划通常用来求最优解,能用动态规划解决的求最优解问题,必须满足最优解的每个局部解也都是最优的

    实际上,递归的思想在编程时未必要实现为递归函数。在这道题中不需要写递归函数,从第n-1行元素开始向上递推,就能求得最终解。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    
    int main()
    {
        int n;
        int a[110][110];
        cin >> n;
        for(int i = 0; i < n; i++)
            for(int j = 0; j <= i; j++)
                cin >> a[i][j];
        for(int i = n - 1; i >= 0; i--) {
            for(int j = 0; j <= i; j++) {
                a[i][j] += a[i + 1][j] > a[i + 1][j + 1] ? a[i + 1][j] : a[i + 1][j + 1];
            }
        }
        cout << a[0][0];
        return 0;
    }
  • 相关阅读:
    编程命名规范化
    傻孩子菜单框架(转)
    《数据结构》示范程序树的长子-兄弟表示法
    keil中编译时出现*** ERROR L107: ADDRESS SPACE OVERFLOW
    单片机C语言下LCD多级菜单的一种实现方法
    指针函数与函数指针的区别
    LCD1602汉字、自定义字符取模
    FFmpeg纯净版解码 av_parser_parse2
    ffmpeg 内存读写相关
    AudioSpecificConfig
  • 原文地址:https://www.cnblogs.com/xzrmdx/p/5148810.html
Copyright © 2011-2022 走看看