區間 DP
代表 之間的所有狀態的整合結果。
遞迴和迴圈都是常見實作方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 | int dp[N][N];
// 遞迴
void f(int L, int R)
{
if (L > R)
return;
if (dp[L][R] != 0)
return;
for (int i = L; i <= R; ++i)
{
f(L, i);
f(i, R);
dp[L][R] = ...;
}
return;
}
// 迴圈
for (int i = 1; i < N; ++i)
for (int L = 0; L + i < N; ++L)
{
R = L + i;
for (int k = L; k <= R; ++k)
{
dp[L][R] = ...;
}
}
|
UVa 10003 - Cutting Sticks
有一根木棍長度為 要往 個點 切開,切木棍的成本 木棍長度,問最小成本為多少?
先增加兩個點
參考程式碼
1
2
3
4
5
6
7
8
9
10
11
12
13 | int c[N], dp[N][N];
int f(int L, int R)
{
if (dp[L][R] != -1)
return dp[L][R];
if (L == R - 1)
return dp[L][R] = 0;
dp[L][R] = INT_MAX;
for (int i = L + 1; i < R; ++i)
dp[L][R] = min(dp[L][R], f(L, i) + f(i, R) + (c[R] - c[L]));
return dp[L][R];
}
|
矩陣相乘問題
兩個矩陣 相乘需要操作 次。給定 個矩陣 ,矩陣相乘順序不影響結果,請問最少相乘次數為何?
- 狀態: 從第 個矩陣相乘到第 個矩陣的最少相乘次數
- 初始狀態:
- 轉移式子:
UVa 00348 - Optimal Array Multiplication Sequence
承接矩陣相乘問題,需要輸出優先相乘順序,用括號表示。
在轉移過程中多維護一個陣列 紀錄每個區間的最佳分割點,輸出的時候根據 的結果遞迴輸出答案。
參考程式碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 | int f(int L, int R)
{
if (L == R)
return dp[L][R] = 0;
if (dp[L][R] != -1)
return dp[L][R];
dp[L][R] = INT_MAX;
for (int i = L; i < R; ++i)
{
int res = f(L, i) + f(i + 1, R) + x[L] * x[i + 1] * x[R + 1];
if(res < dp[L][R])
{
dp[L][R] = res;
to[L][R] = i;
}
}
return dp[L][R];
}
void dfs(int L, int R)
{
if(L==R)
{
cout << "A" << L + 1;
return;
}
if(L==R-1)
{
cout << "(A" << L + 1 << " x A" << R + 1 << ")";
return;
}
cout << "(";
dfs(L, to[L][R]);
cout << " x ";
dfs(to[L][R] + 1,R);
cout << ")";
}
|
最佳二元搜尋樹
給定 個元素的搜尋頻率(機率) ,假設元素在二元搜尋樹的深度 ,請找出一顆二元搜尋樹讓 最小。
- 和霍夫曼樹的差異:元素的相對位置是固定的,沒辦法移動。
- 狀態: 由第 個元素到第 個元素形成的(子)樹最小 cost。
- 初始狀態:
- 轉移式子:
例題練習
- UVa 10559
- UVa 1351
- UVa 1626
- UVa 1630
- AtCoder Educational DP Contest - N
- AtCoder Educational DP Contest - L