• DP问题之数塔问题


    问题描述:考虑下面的数字金字塔,写一个程序来计算从最高点开始,在底部任意处结束经过的数字和最大,每一步可以走到左下和右下的点。

      7

    3   8

        8   1   0

      2   7   4   4

    4   5   2   6   5

    变形后:

    7

    3   8

    8   1   0

    2   7   4   4

    4   5   2   6   5

    问题分析:可以先对金字塔进行变形,如上。对于数字金字塔可以用(i, j)来表示数字在金字塔中的位置。

    对于金字塔中间的一点,想要经过它,则必须经过它的左上或上面的点(变形后)。因此要使经过该点的和最大,则是在经过左上和右上的点中较大的“最大和”,

    然后加上该点的值。这样,状态很明显是金字塔的层。

    设计一个二维状态opt[i, j]表示到第 i 行 第 j 列的最大和,那么决策就是opt[i-1, j-1]和opt[i-1, j]中较大值在加上(i, j)处的值。

    状态转移方程为:

    opt[i, j] = opt[i-1, j] + a[i, j]  j=1 //左边缘

    opt[i, j] = opt[i-1, j-1] + a[i, j]   j=i //右边缘

    opt[i, j] = max{opt[i-1, j-1], opt[i-1, j]} + a[i, j];  1<j<i

    最后的答案:ans = max{opt[n, i]}  1 <= i <= n;

    还有一点就是:其实从上往下和从下往上走是一样的,从下往上走时,可以省下求最大值的步骤,最终结果就是opt[1,1],状态方程为:

    opt[i, j] = max{opt[i+1, j], opt[i+1, j+1]} + a[i, j] ;

    测试代码:

    #include <stdio.h> 
    #include
    <stdlib.h> 

    int main()
    {
    int a[5][5] = {
    {
    7, 0, 0, 0, 0},
    {
    3, 8, 0, 0, 0},
    {
    8, 1, 0, 0, 0},
    {
    2, 7, 4, 4, 0},
    {
    4, 5, 2, 6, 5}
    };
    int opt[5][5];
    int i, j;

    for(i=0; i<5; i++)
    opt[
    4][i] = a[4][i];//初始化最后一行

    for(i=3; i>=0; i--)
    for(j=0; j<=i; j++)
    if(opt[i+1][j]>opt[i+1][j+1])
    opt[i][j]
    = opt[i+1][j] + a[i][j];
    else
    opt[i][j]
    = opt[i+1][j+1] + a[i][j];

    printf(
    "max:%d\n", opt[0][0]);
    return0;
    }
  • 相关阅读:
    百度ECharts数据绑定诀窍
    SQL操作Json数据
    c# 如何得到一个字符的ASCII码
    Sql数据库收缩 语句特别快
    Hive中 使用 Round() 的坑
    [转]Hive 数据类型
    [转] Hive函数大全
    使用Hive Rest API 连接HDInsight
    Hive动态分区 参数配置及语法
    Js的引用赋值与传值赋值
  • 原文地址:https://www.cnblogs.com/lovesaber/p/2033321.html
Copyright © 2020-2023  润新知