1 數塔問題
1.1 思路
把每乙個點看成乙個狀態,即從每個狀態開始到達終點的最大值稱為它的狀態值,由此可見,每乙個點的最大值,與它所連的兩個點的狀態值的大小密切相關。對此,我們引出乙個方程。
狀態轉移方程
:d(i, j) = a(i, j) + max
1.2 解決方法
方法一:遞迴計算
int solve(int i, int j)
大家可以看到,這樣做有些點會計算到兩次,所以它的效率還不是最高的。
方法二:遞推計算
int i, j;
for(j = 1; j <= n; j++) d[n][j] = a[n][j];
for(i = n - 1; i >= i; j++)
for(j = 1; j <= i; j++)
d[i][j] = a[i][j] + max(d[i + 1][j], d[i + 1][j + 1]);
方
法三:記憶化搜尋
先用memset(d, -1, sizeof(d);把
d全部初始化為
-1,這樣,我們就可以通過結點值是否為
-1來判斷它是否被計算過。從而保證了每個結點只訪問了一次。
int solve(int i, int j)
1.3 總結
利用動態記錄節點的值,並且只要保證每個節點只計算一次,就可以得到效率最高的演算法。
樣例**:
#include#includeusing namespace std;
int a[20][20];
int d[20][20];
int n;
int max(int a, int b)
int solve(int i, int j)
int main()
如要輸出路徑,參見小學期**
1000
數塔。2 dag上的動態規劃(有向無環圖)
2.1巢狀矩形問題
2.1.1 問題簡述:給定一組矩形,使盡量多的矩形排成一行,使每乙個矩形都可以巢狀在下乙個矩形內,如有多解,矩形編號的字典序應盡量小。
2.1.2 問題分析:這是
dag中不固定起點的最長路徑問題,設
d(i)
表示從節點
i出發的最長路徑長度,則我們可以得出狀態轉移方程:
d(i) = max,其中
e為邊集。
2.1.3 樣例**
int dp(int i)
注意這裡的引用,每一次對ans的讀寫實際上也就是對
d[i]
的讀寫。
2.1.4 **深化
注意要求中的如有多個最優解,矩形編號的字典序應最小。將所有d值計算出來以後,選擇最大的
d[i]
所對應的最小的
i值,就能保證字典序最小了,並且我們能夠將路徑列印出來。
2.1.5 完整**
#includeusing namespace std;
//巢狀矩形問題
int n;
int a[20], b[20], d[20] = ;
int matrix[20][20] = ;
void creatmatrix()
}int max(int x, int y)
int dp(int i)
void print_ans(int i)
}int main()
creatmatrix();
for(int i = 0; i < n; i++)
dp(i);
int min(10);
for(int i = 0; i < n; i++)
cout << "最多有" << d[min] << "個矩形可完成巢狀,它們的編號依次為:" << endl;
print_ans(min);
return 0;
}
動態規劃系列一(數塔問題)
有形如下圖所示的數塔,從頂部出發,在每一結點可以選擇向左走或是向右走,一直走到底層,要求找出一條路徑,使路徑上的值最大 input 輸入資料首先包括乙個整數c,表示測試例項的個數,每個測試例項的第一行是乙個整數n 1 n 100 表示數塔的高度,接下來用n行數字表示數塔,其中第i行有個i個整數,且所...
動態規劃 矩形巢狀問題
矩形巢狀 時間限制 3000 ms 記憶體限制 65535 kb 難度 4 描述 有n個矩形,每個矩形可以用a,b來描述,表示長和寬。矩形x a,b 可以巢狀在矩形y c,d 中當且僅當a根據題意,首先可以想象的到,如果乙個矩形能鑲嵌另乙個矩形,那麼這個矩形的面積就一定比另乙個矩形的面積大了。所以,...
動態規劃 數塔問題
有如下所示的數塔,要求從頂層走到底層,若每一步只能走到相鄰的結點,則經過的結點的數字之和最大是多少?從頂點出發時到底向左走還是向右走應 取決於是從左走能取到最大值還是從右走能取到最大值,只要左右兩道路徑上的最大值求出來了才能作出決策。同樣的道理下一層的走向又要取決於再下一層上的最大值是否已經求出才能...