動態規劃之數塔問題
阿新 • • 發佈:2018-12-16
- 教材習題6第1題。
有數字三角形如下:
找出從第一層到最後一層的一條路,使得所經過的權值之和最小或者最大。
#include<iostream> using namespace std; const int N=50; int main() { cout << "Please input N(lines): " ; //數塔的層數 int n; cin >> n; int d[N+1][N+1][3]; //[1]用來存數,[2]參與運算,[3]表示向左(0),還是向右(1) //輸入數塔 for(int i = 1; i <= n; ++i) { cout << "Please input line"<< i<<": "; for(int j = 1; j <= i; ++j) //第i行有i個數 { cin >> d[i][j][1]; d[i][j][2] = d[i][j][1]; d[i][j][3] = 0; } } cout << endl; for( i = n-1; i >= 1; --i) //從倒數第二行開始 { for(int j=1; j <= i; j++) { if (d[i+1][j][2] > d[i+1][j+1][2]) { d[i][j][2] += d[i+1][j][2]; d[i][j][3] = 0; } else { d[i][j][2] += d[i+1][j+1][2]; d[i][j][3] = 1; } } } //輸出數塔 for( i = 1; i <= n; ++i) { for(int j = 1; j <= i; ++j) { cout << d[i][j][1] << " "; } cout << endl; } cout << "Max:"<<d[1][1][2] << endl; //輸出路徑 int j; for(i = 1, j = 1; i<= n; ++i) { cout << "[" << i << "," << j << "]" << " -> "; j += d[i][j][3]; } cout << "結束"<<endl; return 0; }
結果如下:
提示:
以所經過的權值之和最大值為例進行說明。
行進的過程中,每次只有兩種選擇:向左或向右。一個有n層的數字三角形的完整路徑有2n條,所以當n比較大的時候,搜尋全部路徑,從中找出最大值,效率較低。
採用動態規劃方法實現。
用d(i,j)表示從位置(i,j)出發時得到的最大值(包括位置(i,j)本身),可以寫出最大值的遞迴方程:
由於遞迴方程中包含了重複子問題,直接採用遞迴方程求解, 效率較低。採用動態規劃的方法,用一張二維表記錄中間過程的值,可以把時間效率提高到n2。