数字三角形问题[动态规划]
问题:
给定一个由n行数字组成的数字三角形,如下图所示:
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
试设计一个算法,计算出从三角形的顶至底的一条路径,使该路径经过的数字总和最大(每一步只能从一个数走到下一层上和它最近的左边的数或者右边的数)。
输入:
第一行是数字三角形的行数,接下来 n 行是数字三角形中的数字。
比如:
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出:
输出这个最大值。
分析&算法思路:
设 d( i , j )表示数字三角形中的第 i 行第 j 个点。
max[i][j]表示 第 i 行 第 j 个数字到低端的最佳路径之和,则原问题的解就是 max[1][1] 的值了。
从d( i , j )这个点向下走,显然只能走 d( i +1, j ) 和 d( i+1 , j+1 ) 这两个点了。
而 max[i][j] 的最优值= d( i , j ) 的值 + max{ max[i+1][j] ,max[i+1][j+1] }。
所以,我们可以至底向上来计算。先计算最后一层的点的,然后倒二层的,……,一直算到第一层。
算法:
#include<iostream> #include<fstream> using namespace std; void main() { ifstream input("input.txt"); ofstream output("output.txt"); int n; int s[101][101] = { 0 }; input >> n; for (int i = 1; i <= n; i++) { for (int j = 1; j <= i; j++) { input >> s[i][j]; } } int max[101][101] = { 0 }; for (int i = 1; i <= n; i++) { //初始化,最下面一层的max数组就是三角形最下面一层的值 max[n][i] = s[n][i]; } for (int i = n - 1; i >= 1; i--) {//从倒数第二层向上计算 for (int j = 1; j <= i; j++) {//计算第 i 层的每一个点的 max[][] int one = max[i + 1][j];//要么向下一层上和它最近的左边走 int two = max[i + 1][j + 1];//要么向下一层上和它最近的右边走 if (one > two) { max[i][j] = s[i][j] + one; } else { max[i][j] = s[i][j] + two; } } } output << max[1][1]; input.close(); output.close(); }