zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    华为2016校园招聘上机笔试题
    android SQLite 使用
    handler
    fragment 给 activity 传数据
    activity 给 fragment 传递数据
    fragment (动态加载)
    fragment (静态)
    Java学习随笔之磨刀篇——环境搭建+问候世界
    Go语言设计哲学
    Ubuntu设置护眼程序
  • 原文地址:https://www.cnblogs.com/lovesaber/p/2033321.html
Copyright © 2011-2022 走看看