动态规划算法设计
标签(空格分隔): 算法知识文档 动态规划
动态规划设计要素
- 问题建模,优化的目标函数是什么?约束条件是什么?
- 如何划分子问题(边界)?
- 问题的优化函数值与子问题的优化函数值之间存在着什么以来关系?(递推方程)
- 是否满足优化原则?
- 最小子问题怎样界定?其优化函数值,即初始值等于什么?
矩阵链相乘
问题:
设 A1,A2,...,An A 1 , A 2 , . . . , A n 为矩阵序列, Ai A i 为 Pi−1∗Pi P i − 1 ∗ P i 阶矩阵, i=1,2,...,n i = 1 , 2 , . . . , n 试确定矩阵的乘法顺序,使得元素相乘的总次数最少.
输入:
向量 P=<P0,P1,...,Pn>, P =< P 0 , P 1 , . . . , P n > , 其中 P0,P1,...,Pn P 0 , P 1 , . . . , P n 为 n n 个矩阵的行数与列数,比如是第一个矩阵的行数, P1 P 1 是第一个矩阵的列数同时是第二个矩阵的行数,以此类推. pn p n 是第 n−1 n − 1 个矩阵的行数,是第 n n 个矩阵的列数.
输出:
矩阵链乘法加括号的位置
矩阵相乘基本运算次数
矩阵: i i 行列, B B : 行 k k 列,以元素相乘作为基本运算,计算的工作量, AB=C,C A B = C , C 有 i i 行列个元素,计算每一个元素需要做的乘法次数是 j j 次,所以计算需要做 i∗j∗k i ∗ j ∗ k 次乘法.
实例:
输入:
P=<10,100,5,50>
P
=<
10
,
100
,
5
,
50
>
A1:10∗100,A2:100∗5,A3:5∗50
A
1
:
10
∗
100
,
A
2
:
100
∗
5
,
A
3
:
5
∗
50
乘法次序:
(A1A2)A3:10∗100∗5+10∗5∗50=7500
(
A
1
A
2
)
A
3
:
10
∗
100
∗
5
+
10
∗
5
∗
50
=
7500
A1(A2A3):100∗5∗50+10∗100∗50=75000
A
1
(
A
2
A
3
)
:
100
∗
5
∗
50
+
10
∗
100
∗
50
=
75000
第一种次序计算次数最少
蛮力算法:
枚举所有加上括号的可能,复杂度是指数级的.
动态规划算法
子问题的划分:
Ai...j
A
i
.
.
.
j
: 矩阵链
Ai,Ai+1,...,Aj,
A
i
,
A
i
+
1
,
.
.
.
,
A
j
,
边界
i,j
i
,
j
输入向量
<Pi−1,Pi,...,Pj>
<
P
i
−
1
,
P
i
,
.
.
.
,
P
j
>
<script type="math/tex" id="MathJax-Element-33">
</script>其最好划分的运算次数是:
m[i,j]
m
[
i
,
j
]
子问题的依赖关系:
最优划分最后一次相乘发生在矩阵
k
k
的位置,即:
Ai...j A i . . . j 最优运算次数依赖于 Ai...k A i . . . k 与 Ak+1...j A k + 1... j 的最优运算次数. k∈[i,j) k ∈ [ i , j )
解:
计算得到
Ai...j
A
i
.
.
.
j
最少乘法次数:
m[i][j]
m
[
i
]
[
j
]
下面是计算
m[i][j]
m
[
i
]
[
j
]
也就是说计算得到 Ai...k A i . . . k 是 Pi−1 P i − 1 行 Pk P k 列的矩阵,计算 Ak+1...j A k + 1... j 得到 Pk P k 行 Pj P j 列的矩阵.最后这两个矩阵相乘得到 Pi−1 P i − 1 行 Pj P j 列的矩阵,计算过程取最小就相当于最优决策,当前的最优决策序列是相对于初始和结束的最优决策序列.
实战:Multiplication Puzzle
Language:
Multiplication Puzzle
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 11799 Accepted: 7316
Description
The multiplication puzzle is played with a row of cards, each containing a single positive integer. During the move player takes one card out of the row and scores the number of points equal to the product of the number on the card taken and the numbers on the cards on the left and on the right of it. It is not allowed to take out the first and the last card in the row. After the final move, only two cards are left in the row.
The goal is to take cards in such order as to minimize the total number of scored points.
For example, if cards in the row contain numbers 10 1 50 20 5, player might take a card with 1, then 20 and 50, scoring
10∗1∗50+50∗20∗5+10∗50∗5=500+5000+2500=8000
10
∗
1
∗
50
+
50
∗
20
∗
5
+
10
∗
50
∗
5
=
500
+
5000
+
2500
=
8000
If he would take the cards in the opposite order, i.e. 50, then 20, then 1, the score would be
1∗50∗20+1∗20∗5+10∗1∗5=1000+100+50=1150.
1
∗
50
∗
20
+
1
∗
20
∗
5
+
10
∗
1
∗
5
=
1000
+
100
+
50
=
1150.
Input
The first line of the input contains the number of cards N (3 <= N <= 100). The second line contains N integers in the range from 1 to 100, separated by spaces.
Output
Output must contain a single integer - the minimal score.
Sample Input
6
10 1 50 50 20 5
Sample Output
3650
Source
Northeastern Europe 2001, Far-Eastern Subregion
轻松Accept:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define MAX_N 105
typedef long long LL;
LL dp[MAX_N][MAX_N], p[MAX_N];
int s[MAX_N][MAX_N]; // 标记括号位置
int N;
// 打印追踪解的结果
void printS(){
int i,j;
for(i = 1; i <= N-1; i++){
for(j = 1; j <= N-1; j++){
printf("%d ", s[i][j]);
}
printf("\n");
}
}
void solve(){
int r,i,j,k;
LL tmp;
for(i = 1; i <= N-1; i++) dp[i][i] = 0; // 子问题是1,就是一个矩阵没有相乘次数
for(r = 2; r <= N-1; r++){ // 子问题的长度[2, N-1]
for(i = 1; i <= N-1; i++){ // 计算长度是r的子问题
j = i+r-1; // 右边界
if(j > N-1) continue; // j的范围
else {
dp[i][j] = dp[i+1][j] + p[i-1]*p[i]*p[j]; // k=i的时候
s[i][j] = i; // 追踪解
for(k = i+1; k <= j-1; k++){
tmp = dp[i][k]+dp[k+1][j]+p[i-1]*p[k]*p[j];
if(dp[i][j] > tmp) {
dp[i][j] = tmp; // 更新解
s[i][j] = k; // 追踪解
}
}
}
}
}
printf("%lld\n", dp[1][N-1]);
}
int main(){
freopen("in.txt", "r", stdin);
int i;
while(~scanf("%d", &N) && N){
for(i = 0; i < N; i++) scanf("%lld", &p[i]);
solve();
}
}
问题描述:
小结:
动态规划算法设计要素:
- 多阶段决策过程,每一步处理一个子问题,界定子问题的边界
- 列出优化函数的递推方程及初始值
- 问题要满足优化原则或最优子结构性质,即:一个最优决策序列的任何子序列本身一定是相对于子序列的初始和结束状态的最优决策序列.