动态规划基本思想

基本要素:
(1)最优子结构性质
(2)重叠子问题性质
思想:
动态规划和分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
与分治法不同的是,动态规划法中分解得到的子问题不是互相独立的。若用分治法来解这类子问题,分解得到的子问题数目非常多,最后解决原问题需要耗费指数时间。但是这些子问题有很多是相同的,也就是同一个子问题被计算了很多次,不同子问题的数量可能只有多项式量级。
如果我们保存已经解决的子问题的解,需要解相同子问题时找出已经计算出的解,这样可以减少大量重复计算,最终得到多项式时间算法。
经常用一个来记录所有已解决的子问题的解。不管该子问题以后是否被利用,只要它被计算过,就将其结果填入表中。这就是动态规划的基本思想。具体的动态规划算法多种多样,但它们具有相同的填表格式
—(计算机算法设计与分析 第四版 王晓东)—

动态规划例子:(矩阵连乘问题)

给定N个矩阵{A1,A2,A3,,,,An},其中Ai与A(i+1)是可以相乘的,考察这N个矩阵的连乘积A1*A2*,,,,An。
由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同的计算次序。这种计算次序可以用加括号的方式来确定,比如下面4个矩阵的连乘积。
A1,A2, A3, A4
1,(2,(3,4))
1,((2,3),4)
(1,2),(3,4)
(1,(2,3)),4
((1,2),3),4

最优解的结构

计算A[1:n]的最优次序所包含的计算矩阵子链A[1:k]和A[k+1:n]的次序也是最优的。
A[1:n] = A[1:k] * A[K+1:n] 其中 ( 1 < k < n)
递推关系如下:
m(i , j) = 0 ,(i=j)
m(i , j) = min{ m(i,k) + m(k+1,j) + P(i-1)P(k)P(j) } ,(i < j )

重叠子问题

重叠的子问题主要体现在m表格里,

例题:我们计算如下6个矩阵的连乘积,
A1 —— A2 —— A3 —– A4 —– A5 —– A6
(30*35) (35*15) (15*5) (5*10) (10*20) (20*25)

const int N = 6;
int table[N + 1][N + 1];
int p[N + 1] = { 30, 35, 15, 5, 10, 20, 25 };
void MatrixMulti()
{
    for (int r = 2; r <= N; r++) //r表示连乘矩阵的个数
    {
        for (int i = 1; i <= N - r + 1; i++) //i表示起始矩阵索引
        {
            int j = i + r - 1; //j表示终止矩阵索引
            for (int k = i; k < j; k++)
            {
                int temp = table[i][k] + table[k+1][j] + p[i - 1] * p[k] * p[j];
                table[i][j] = (table[i][j] == 0) ? temp : min(table[i][j], temp);
            }
        }
    }
}
int main()
{
    MatrixMulti();
    cout << "最小乘积为:" <<table[1][N] << endl;
    return 0;
}
/*输出结果:
最小乘积为:15125
table数组内容为:
0       0       0       0       0       0       0
0       0       15750   7875    9375    11875   15125
0       0       0       2625    4375    7125    10500
0       0       0       0       750     2500    5375
0       0       0       0       0       1000    3500
0       0       0       0       0       0       5000
0       0       0       0       0       0       0

*/

猜你喜欢

转载自blog.csdn.net/u010551600/article/details/80909790
今日推荐