質問要件
数値タワーを指定すると、その格納形式は以下に示す下三角行列になります。このナンバータワーでは、上から始めて、一番下に到達するまで各ノードで下または右に進むことを選択できます。パス上の値の合計が最大になるパスを見つけてください。
入力例(ナンバータワー):
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;
}
足りないところがあれば、みんなで提案して一緒に進めていけたらと思います!!!