zoukankan      html  css  js  c++  java
  • 数塔问题

    问题

    有形如下图所示的数塔,从顶部出发,在每一结点可以选择向左走或是向右走,一直走到底层,要求找出一条路径,使路径上的值最大。

    思路

    使用动态规划:

    从顶点出发,向左走、向右走取决于左边大还是右边大,即

    dp[1][1] = max(dp[2][1],dp[2][2])

    看似是自顶向下求解,但是问题中存在重复子问题:第一层的最大值是第一层加上第二层的最大值,而第二层的最大值又是与第二层各个元素连接的第三层的元素最大值加上第二层各元素……

    所以实际求解是自底向上:

    状态转移方程为 dp[i] = max(dp[i+1][j],dp[i+1][j+1]);

    代码:

     1 #include<iostream>
     2 #include<cmath>
     3 #include<algorithm>
     4 #include<vector>
     5 using namespace std;
     6 int f[100][100];
     7 int dp[100][100];
     8 int main()
     9 {
    10     int n;
    11     scanf("%d", &n);
    12     vector<int>list;
    13     for (int i = 1; i <= n; i++)
    14         for (int j = 1; j <= i; j++)
    15             scanf("%d", &f[i][j]);
    16     for (int i = 0; i <= n; i++)
    17         dp[n][i] = f[n][i];
    18     for (int i = n - 1; i >= 0; i--)
    19         for (int j = i; j >= 0; j--)
    20             dp[i][j] = max(dp[i + 1][j], dp[i + 1][j + 1]) + f[i][j];
    21 
    22     int max = dp[1][1];
    23     for (int i = 1; i <= n; i++)
    24     {
    25         for (int j = 1; j <= i; j++)
    26         {
    27             if (max == dp[i][j])
    28             {
    29                 list.push_back(f[i][j]);
    30                 max = max - f[i][j];
    31             }
    32         }
    33     }
    34 
    35     printf("max amount:%d
    ", dp[1][1]);
    36     for (int i = 0; i < list.size(); i++)
    37         printf("%s%d", i == 0 ? "" : " ", list[i]);
    38 }
    39 //5
    40 //9 12 15 10 6 8 2 18 9 5 19 7 10 4 16

     例题

    https://www.luogu.com.cn/problem/P1216

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int dp[1001][1001];
    int list[1001][1001];
    int main()
    {
        int n;
        scanf("%d", &n);
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j <= i; j++)
            {
                int  temp;
                scanf("%d", &temp);
                list[i][j] = temp;
            }
        }
        for (int i = n - 1; i >= 0; i--)
            dp[n - 1][i] = list[n - 1][i];
        for (int i = n - 2; i >= 0; i--)
        {
            for (int j = 0; j <= i; j++)
                dp[i][j] = max(dp[i + 1][j], dp[i + 1][j + 1]) + list[i][j];
        }
        printf("%d", dp[0][0]);
    
    }
  • 相关阅读:
    Entity Framework底层操作封装V2版本号(3)
    从Java到C++——union的使用方法
    静态链接库与动态链接库
    51Nod1446 限制价值树
    2018-8-10-win10-uwp-获取文件夹出错
    2018-8-10-win10-uwp-获取文件夹出错
    2018-10-22-win10-uwp-自定义控件入门
    2018-10-22-win10-uwp-自定义控件入门
    2019-9-2-C#同步方法转异步
    2019-9-2-C#同步方法转异步
  • 原文地址:https://www.cnblogs.com/Jason66661010/p/12790502.html
Copyright © 2011-2022 走看看