地址 https://algospot.com/judge/problem/read/TRIANGLEPATH (leetcode acwing 均有类似题目可供练习)
我们先从 暴力遍历开始说起
每当你处于一个点 有两个选择 选择下面的数字或者选择右下的数字(x+1 || x+1 y+1)
那么每个选择都计算 最后得出sum最大的值就是答案
很明显 这个会TLE
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 5 6 using namespace std; 7 8 const int MAX_N = 100010; 9 10 vector<int> v[MAX_N]; 11 int n, m; 12 int maxsum = -9999999; 13 14 void dfs(int x, int y, int sum) { 15 if (x == m+1 && y < x) { 16 maxsum = max(maxsum, sum); 17 return; 18 } 19 if (x >= m || y > x) 20 { 21 return; 22 } 23 24 sum += v[x][y]; 25 26 dfs(x+1,y,sum); 27 dfs(x+1, y + 1, sum); 28 } 29 30 void solve() 31 { 32 int sum = 0; 33 dfs(0, 0, sum); 34 35 cout << maxsum << endl; 36 } 37 38 int main() 39 { 40 cin >> n; 41 while (n--) { 42 cin >> m; 43 int len = 1; 44 maxsum = -9999999; 45 for (int i = 0; i < MAX_N; i++) { 46 v[i].clear(); 47 } 48 49 for (int i = 0; i < m; i++) { 50 for (int j = 0; j < len; j++) { 51 int t; cin >> t; v[i].push_back(t); 52 } 53 len++; 54 } 55 56 solve(); 57 } 58 59 return 0; 60 }
原因在哪里呢?在如下的三角形里 路线有以下几种
1 2 3 4 5 6 7 8 9 10
1->2->4->7 1->2->4->8 1->2->5->8 1->2->5->9 1->3->5->8 1->3->5->9 1->3->6->9 1->3->6->10
我们可以看到 1->2 1->3的路线重复计算好几次 每次都会去求和
那么我们使用一个表格记录走到2的位置和走到3的位置的最大和 是否就可以避免重复计算
同样其他格子也使用如此思路
再进行观察
7 8 9 10的记录取决于 他们能够倒推到的 4 5 6格子记录的最大和
4 5 6 的记录取决于 他们能够倒推到的 2 3 格子记录的最大和
2 3的记录取决于 他们能够倒推到的 1 格子记录的最大和
1 的格子是确认的 他的最大和就是他自己
有两种推导公式 如下
/*for (int i = m - 1; i >= 0; i--) { for (int j = i; j >= 0; j--) { v[i][j] = max(v[i + 1][j], v[i + 1][j + 1]) + v[i][j]; } } cout << v[0][0] << endl;*/ //==================================================================== /* for (int i = 0; i < m; i++) { for (int j = 0; j <= i; j++) { if (i - 1 >= 0 && j -1 >=0) { dp[i][j] = max( dp[i-1][j]+dp[i][j] , dp[i - 1][j-1] + dp[i][j]); } else if (i - 1 >= 0) { dp[i][j] = dp[i - 1][j]+dp[i][j]; } } } int ret = -999999; for (int i = 0; i < m; i++) { ret = max(ret, dp[m - 1][i]); } cout << ret << endl;
全部代码
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 5 6 using namespace std; 7 8 const int MAX_N = 300; 9 10 vector<vector<int>> v(MAX_N,vector<int>(MAX_N)); 11 int n, m; 12 int maxsum = -9999999; 13 14 vector<vector<int>> dp(MAX_N,vector<int>(MAX_N)); 15 16 17 18 19 20 void solve() 21 { 22 /*for (int i = m - 1; i >= 0; i--) { 23 for (int j = i; j >= 0; j--) { 24 v[i][j] = max(v[i + 1][j], v[i + 1][j + 1]) + v[i][j]; 25 } 26 } 27 cout << v[0][0] << endl;*/ 28 //==================================================================== 29 /* 30 for (int i = 0; i < m; i++) { 31 for (int j = 0; j <= i; j++) { 32 if (i - 1 >= 0 && j -1 >=0) { 33 dp[i][j] = max( dp[i-1][j]+dp[i][j] , dp[i - 1][j-1] + dp[i][j]); 34 } 35 else if (i - 1 >= 0) { 36 dp[i][j] = dp[i - 1][j]+dp[i][j]; 37 } 38 } 39 } 40 41 int ret = -999999; 42 for (int i = 0; i < m; i++) { 43 ret = max(ret, dp[m - 1][i]); 44 } 45 cout << ret << endl; 46 */ 47 } 48 49 int main() 50 { 51 cin >> n; 52 while (n--) { 53 cin >> m; 54 int len = 1; 55 maxsum = -9999999; 56 for (int i = 0; i < MAX_N; i++) { 57 for (int j = 0; j < MAX_N; j++) { 58 v[i][j] = 0; 59 //dp[i][j] = 0; 60 } 61 } 62 63 for (int i = 0; i < m; i++) { 64 for (int j = 0; j < len; j++) { 65 cin >> v[i][j]; 66 dp[i][j] = v[i][j]; 67 } 68 len++; 69 } 70 71 solve(); 72 } 73 74 return 0; 75 }