動的計画法 - 数値タワー問題

質問要件

数値タワーを指定すると、その格納形式は以下に示す下三角行列になります。このナンバータワーでは、上から始めて、一番下に到達するまで各ノードで下または右に進むことを選択できます。パス上の値の合計が最大になるパスを見つけてください。

入力例(ナンバータワー):

9

12 15

10 6 8

2 18 9 5

19 7 10 4 16

出力サンプル (最大パス合計):

59

質問分析

動的計画法を一言で説明すると「前にやったことを思い出す」ですが、より正確に言えば「前に得た答えを思い出す」です。

この問題については、上から下に分析し、下から上に計算できます。

つまり、常に上から最大のものを選択し、貪欲なアルゴリズムを使用するのは間違っています。なぜなら、あるノードの次のノードが大きいか小さいかがわからないからです。

したがって、下から上への最大パスを見つけて、2 番目のレベルまで最大値を更新し続けることができます。1 日の最大パスを選択しました。

例としてトピックを取り上げます。

5層目のデータは 19 7 10 4 16

4 階から開始: 2を選択した場合、5 階 (19、7) では19を選択する必要があります。

                             この場合、最大パスは 2—>19 =  21 のみになります。

18 を                            選択した場合、5 階 (7、10) では10を選択する必要があります。

                             この場合、最大パスは  18—>10 =  28 のみになります。

9                            を選択した場合、5 階 (10、4) では10を選択する必要があります。

                             この場合、最大パスは 9—>10 =  19 のみになります。

5                            を選択した場合、5 階 (4、16) では16を選択する必要があります。

                              この場合、最大パスは  5—>16 =  21 のみになります。


3 番目の層: 10を選択した場合、4 番目の層 (2, 18) では18 (28>21)を選択する必要があります。

                             この場合、最大パスは 10—>18—>10 =  38 のみになります。

6                                           を選択した場合、4 階 (18、9) では18 を選択する必要があります (28>19)

                             この場合、最大パスは  6—>18—>10 =  34 のみになります。

8                                    を選択した場合、4 番目のレベル (9、5) では5 (21>19)を選択する必要があります。

                             この場合、最大パスは 8—> 5—>16 =  29 のみになります。

……

同様に、第 2 レベルまでは、第 1 レベルから選択する方法がわかります。第 2 レベルの最大パスを追加したものが、問題で必要な最大パスになります。

表に表すと次のようになります。

59

50

49

38

34

29

21

28

19

21

19

7

10

4

16

コード実装分析

#include <iostream>
#include <algorithm>

using namespace std;


int data[50][50];//存储原始数据
int dp[50][50];//存储动态规划过程中的数据
int n;//塔的层数

void ShuT()
{
    //先将数塔最底层数据放入动态规划dp数组第五层
    for (int i = 0; i < n; ++i)
    {
        dp[n - 1][i] = data[n - 1][i];
    }  


    //临时存放向下向右两个值的,最大那个
    int temp_max;


    //开始往dp数组中存放每个小阶段的路径值
     
   for (int i = n - 1; i >= 0; --i)     //层数,从下往上进行
    {
        for (int j = 0; j <= i; ++j)    //不同层数值的位置
        {
            // 使用递推公式计算dp的值
            temp_max = max(dp[i + 1][j], dp[i + 1][j + 1]); //取向下,向右的最大值
            dp[i][j] = temp_max + data[i][j];              //dp数组存放当前路径的最大值
        }
    }

}


int main()
{
   
    cin>>n;
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j <= i; ++j)
        {
            cin >> data[i][j];
        }
    }

    ShuT();
     cout << "最大路径和:" << dp[0][0] <<endl;
}

足りないところがあれば、みんなで提案して一緒に進めていけたらと思います!

おすすめ

転載: blog.csdn.net/weixin_59367964/article/details/127936967