算法分析 - 动态规划算法解矩阵连乘(动态规划)

【问题描述】使用动态规划算法解矩阵连乘问题,具体来说就是,依据其递归式自底向上的方式进行计算,在计算过程中,保存子问题答案,每个子问题只解决一次,在后面计算需要时只要简单查一下得到其结果,从而避免大量的重复计算,最终得到多项式时间的算法。
【输入形式】在屏幕上输入第1个矩阵的行数和第1个矩阵到第n个矩阵的列数,各数间都以一个空格分隔。
【输出形式】矩阵连乘A1…An的最少数乘次数和最优计算次序。
【样例1输入】
30 35 15 5 10 20 25
【样例1输出】
15125
((A1(A2A3))((A4A5)A6))
【样例说明】
输入:第1个矩阵的行数和第1个矩阵到第6个矩阵的列数,以一个空格分隔。
输出:矩阵连乘A1…An的最少数乘次数为15125,最优计算次序为((A1(A2A3))((A4A5)A6))。
【评分标准】根据输入得到准确的输出。

基本思想:
矩阵连乘可以抽象为:
dp[i][j]:从矩阵i到矩阵j连乘所需要的最小乘数
则可以推理出等式:
dp[i][j] = dp[i][k] + dp[k+1][j] + a[i-1]*a[k]*a[j]
(其中a[i]是i矩阵的列数)
可明显发觉dp[i][j]的子问题也是最优解
因此可以使用递归的方式求解
并且可发展为动态规划来进行算数优化

#include <iostream>
#include <cstdio>

using namespace std;

const int maxn = 1005;
int t = 0, n = -1;
int a[maxn] = {0};
int dp[maxn][maxn] = {0};
int bac[maxn][maxn] = {0};

void TraceBack(int l, int r) {
    if(l == r) {
        printf("A%d", l);
    }
    else {
        printf("(");
        TraceBack(l, bac[l][r]);
        TraceBack(bac[l][r]+1, r);
        printf(")");
    }
}

int main() {
    while(scanf("%d", &a[++n]) != EOF) {} n--;
    for(int k = 2; k <= n; ++k) {
        for(int i = 1; i <= n-k+1; ++i) {
            int j = i+k-1;
            dp[i][j] = dp[i+1][j] + a[i-1] * a[i] * a[j], bac[i][j] = i;
            for(int m = i+1; m < j; ++m) {
                t = dp[i][m] + dp[m+1][j] + a[i-1] * a[m] * a[j];
                if(t < dp[i][j]) {
                    dp[i][j] = t, bac[i][j] = m;
                }
            } 
        }
    }
    printf("%d\n", dp[1][n]);
    TraceBack(1, n);
    return 0;
}
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值