問題:
給定一個由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(); }