挑戰程序設計競賽 2.3章習題 poj 3176 Cow Bowling dp
地址 http://poj.org/problem?id=3176

經典動態規劃問題 給出一個數值均在0~99之間的三角形 請問從第一行的數字出發,每次可選擇下一行相鄰的兩個數字中的一個,請問達到底層的時候選擇的所有數字和最大是多少 輸入 第一行一個數字N 表示三角形有N行,后面N行每行有1~N個空格隔開的數字 輸出 一行 包含一個答案數字
解法
動態規劃
因為每層每個點都有2中選擇(下一行相鄰的兩個點)
而上一層到達該點的方法也有兩種
n層三角形總的路徑又有2(n-1) 如果使用dfs求出全部路徑再找最大和,時間不允許

但是我們注意到 上一層兩點arr[i-1][j]和arr[i-1][j+1] 到達arr[i][j]的時候 我們肯定選擇路徑和最大的方案
同樣的 arr[i][j]到達下一層兩個的選擇arr[i+1][j] arr[i+1][j+1]中 我們也肯定選擇路徑和最大的方案 其余方案忽略
雖然某層的路徑和最大比較難以確定,但是第0層選擇到第1層的方案是可以快速求得的
然后第1層確定, 再來確定第2層也可以快速求得
如此遞推 確定N層求N+1層的最大路徑和

逆向觀察 如果三角形只有最下面兩層
那么上面一層每個點該如何選擇路徑使得路徑和最大也是可以快速求得

配圖
// 1123555.cpp : 此文件包含 "main" 函數。程序執行將在此處開始并結束。 // #include <iostream> #include <algorithm> using namespace std; /* Sample Input 5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 Sample Output 30 */ const int N = 370; int arr[N][N]; int n; int main() { cin >> n; for (int i = 0; i < n; i++) { for (int j = 0; j <= i; j++) { cin >> arr[i][j]; } } #if 1 for (int i = n - 2; i >= 0; i--) { for (int j = 0; j <= i; j++) { int val = max(arr[i+1][j], arr[i+1][j + 1]); arr[i][j] += val; } } cout << arr[0][0] << endl; #else for (int i = 1; i < n; i++) { for (int j = 0; j <= i; j++) { int val = arr[i][j]; if (j < i) { arr[i][j] = max(arr[i][j], val + arr[i - 1][j]); } if (j > 0) { arr[i][j] = max(arr[i][j], val + arr[i - 1][j - 1]); } } } int ans = 0; for (int i = 0; i < n; i++) { ans = max(ans, arr[n - 1][i]); } cout << ans << endl; #endif return 0; }
作 者: itdef
歡迎轉帖 請保持文本完整并注明出處
技術博客 http://www.rzrgm.cn/itdef/
B站算法視頻題解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
歡迎c c++ 算法愛好者 windows驅動愛好者 服務器程序員溝通交流
如果覺得不錯,歡迎點贊,你的鼓勵就是我的動力
歡迎轉帖 請保持文本完整并注明出處
技術博客 http://www.rzrgm.cn/itdef/
B站算法視頻題解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
歡迎c c++ 算法愛好者 windows驅動愛好者 服務器程序員溝通交流
如果覺得不錯,歡迎點贊,你的鼓勵就是我的動力
浙公網安備 33010602011771號