动态规划 - 矩阵连乘问题(笔记)

题目描述:

给定n个矩阵{A1,A2,…An},其中Ai 与Ai+1 是可乘的,i = 1,2,3…n-1。考查这n 个矩阵的连乘积A1A2….An。
比如A1A2A3,可以有(A1A2)A3,A1(A2A3) 这两种方式。

思路:

若使用穷举搜索法,其复杂度是随着n的增长呈指数增长的,可以使用动态规划的时候,即求其最优子结构。设AiAi+1…Aj记作A[i : j],设A[i : j],1 <= i <= j <= n,所需要的最少数乘次数为m[i][j].则有:
m[i][j] = 0, i = j;
m[i][j] = min{m[i][k] + m[k+1][j] + pi - 1pkpj }, i < j .
s[][]用来记录最优解的位置,最后通过递归的方式,确定最后的计算次序。
首先要明确的是:所给出的矩阵必须是可以连乘的!
下面给出我们假设要计算的数据是,A1A2A3A4A5A6,其中A1:30*35,A2:35*15,A3:15*5,A4:5*10,A5:10*20,A6:20*25
所以我们的p数组的值为,p[] = {30,35,15,5,10,20,25};

代码:

要理解m,s的意义,以及在取最优解的时候的操作。可以在纸上模拟一下,还是比较好理解的。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// m[i][j]:从第i个数组到第j个数组,求最优值数组,s[][]:最优断开位置的数组
//n 表示测试数组的个数
int matrixChan(int *p,int n, int **m, int **s)
{
//  int n = strlen(p);
    for(int i = 1; i <= n; i ++)
        m[i][i] = 0;
    for(int r = 2; r <= n; r ++) //r为连乘矩阵的个数 
    {
        for(int i = 1; i <= n - r + 1; i ++)
        {
            int j = i + r - 1;  // i 表示起始,j表示第r个 
            m[i][j] = m [i + 1][j] + p[i - 1]*p[i]*p[j];
            s[i][j] = i;
            for(int k = i + 1; k < j; k ++)  //在第一个到第r个数组连乘,寻找最优的断开点 
            {
                int t = m[i][k] + m[k + 1][j] + p[i - 1]*p[k]*p[j];
                if(t < m[i][j])
                {
                    m[i][j] = t;
                    s[i][j] = k;
                }
            }
        }
    }
    return m[1][n]; // 返回第一个到第n个,即题目给出数据的答案 
}

void traceback(int **s, int i, int j)
{
    if(i == j)
        return;
    traceback(s, i, s[i][j]);
    traceback(s, s[i][j] + 1, j);
    printf("Multiply A %d,%d and A %d,%d\n", i,  s[i][j] ,(s[i][j] + 1), j );
}

int main()
{
    int p[6];
    p[0] = 30;   
    p[1] = 35;     
    p[2] = 15;     
    p[3] = 5;     
    p[4] = 10;     
    p[5] = 20;    
    p[6] = 25;     
    //new出测试的数组。 
    int **m, **s;
    int n = 7;
    m = (int **)malloc(n*sizeof(int *));
    s = (int **)malloc(n*sizeof(int *));

    for (int i = 0; i < n; i++)
    {
        m[i] = (int *)malloc(n*sizeof(int));  
        s[i] = (int *)malloc(n*sizeof(int));
    }

    int ans = matrixChan(p,6, m, s);
    printf("%d\n",ans);
    traceback(s, 0, 6);
}

结果:

这里写图片描述

从最后的结果可以看出,最优的次数是15125,然后最优的计算次序是((A1(A2A3)) ((A4A5)A6)) .

Matrixchain的计算量取决于r,i,k的循环,为O(n3),空间复杂度为O(n2)。相比与穷举搜索更加高效。

尾巴:

不知道为啥,最近失眠超级严重的,特别是周六的晚上,于是乎,写完这篇已经快凌晨4点了,而我还是毫无睡意。

大三、、、、2015、11、01 03:45

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值