动态规划 矩阵连乘问题

什么是动态规划

这里写图片描述

看到把原始问题划分成一系列子问题,我们很容易想到分治算法,但是对于分治算法,很可能会遇到子问题被重复使用
就像下面这个矩阵连乘,分解为子问题就会出现三个重复子问题,用分治算法时,就会重复计算相同的子问题,使程序效率变得低下

所以,这就是动态规划的用武之地:对于一个问题,可分为多个相关子问题,子问题的解被重复使用

这里写图片描述

矩阵连乘问题

对于矩阵连乘,假设A为10 * 100 的矩阵, B为100 * 5 的矩阵,C为5 * 50的矩阵,那么有两种情况:
1、(A * B) * C 一共要乘 10 * 100 * 5 + 10 * 5 * 50 = 7500次
2、A * (B * C) 一共要乘 100 * 5 * 50 + 10 * 100 * 50 = 750000次

可以看到,不同顺序的相乘,就会有不同的时间复杂度,动态规划就是要来求一个最优解。

把这个括号的位置设为k,那么(A * B) * C 的k值就为2,表示A 和 B的矩阵先乘;A * (B * C) 的 k 值为 1, 表示B 和 C的矩阵相乘。

那么我们要做的就是如何确定这个k值,使得矩阵相乘具有最优解。

这里写图片描述

m[i, j]是指矩阵 i 到 矩阵 j 相乘的最小乘法数
p之间相乘是指拆分的矩阵之间的相乘

对于A * B * C:
m[1,3] = m[1,1] + m[2, 3] + p0 * p1 * p3 的意思是 A * (B * C)
m[1,3] = m[1,2] + m[3, 3] + p0 * p2 * p3 的意思是 (A * B) * C

也可以用这个图来理解

这里写图片描述

这里写图片描述

例如求m[1, 3] 就是 求 m[1, 1] 和 m[2, 3] 或者 求 m[1, 2] 和 m[3, 3。

代码实现

#include <iostream>  
#include <cstdio>  
#include <cstring>  

using namespace std;  

#define SIZE 100  
#define INF 999999999  

int p[SIZE];         
int m[SIZE][SIZE];  //存放矩阵链计算的最优值,d[i][j]为第i个矩阵到第j个矩阵的矩阵链的最优值

int Best_DP(int n)  
{  

    memset(m, 0, sizeof(m));  

    int len;  

    for (len = 1; len <= n; len++)  
    {  
        int i, j, k;  
        for (i = 1, j = i+len; j <= n; i++, j++)  
        {  
            int min = INF;   
            for (k = i; k < j; k++)  
            {  
                int count = m[i][k] + m[k+1][j] + p[i-1] * p[k] * p[j];  
                if (count < min)  
                {  
                    min = count;  
                }  
            }  
            m[i][j] = min;  
        }  
    }  
    return m[1][n];  
}  

int main(void)  
{  
    int n;  
    while (scanf("%d", &n) != EOF)  
    {  
        int i;  
        for (i = 0; i <= n; i++)  
        {  
            scanf("%d", &p[i]);  
        }  

        printf("%d\n", Best_DP(n));  
    }  
    return 0;  
}  

这里需要注意的是:

  1. n是指相乘的矩阵数目
  2. p用来存放各矩阵的信息: 用p[i - 1] 和 p[i]来表示第i个矩阵的行和列,例如 A为10 * 100 的矩阵, B为100 * 5 的矩阵,C为5 * 50的矩阵,则p[0] = 10 , p[1] = 100, p[2] = 5 , p[3] = 50
  3. m[i, j]用来表示i 到 j矩阵相乘的最优解

时间复杂性和空间复杂性

这里写图片描述

  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值