zoukankan      html  css  js  c++  java
  • 矩阵最优连乘问题(区间DP+记忆化)

    Description

    在科学计算中经常要计算矩阵的乘积。矩阵A和B可乘的条件是矩阵A的列数等于矩阵B的行数。若A是一个p×q的矩阵,B是一个q×r的矩阵,则其乘积C=AB是一个p×r的矩阵。

    由公式知计算C=AB总共需要pqr次的数乘。

    为了说明在计算矩阵连乘积时加括号方式对整个计算量的影响,我们来看一个计算3个矩阵{A1,A2,A3}的连乘积的例子。设这3个矩阵的维数分别为10×100,100×5和5×50。若按第一种加括号方式((A1A2)A3)来计算,总共需要10×100×5+10×5×50=7500次的数乘。若按第二种加括号方式(A1(A2A3))来计算,则需要的数乘次数为100×5×50+10×100×50=75000。第二种加括号方式的计算量是第一种加括号方式的计算量的10倍。由此可见,在计算矩阵连乘积时,加括号方式,即计算次序对计算量有很大影响。

    于是,人们自然会提出矩阵连乘积的最优计算次序问题,即对于给定的相继n个矩阵{A1,A2,…,An}(其中Ai的维数为pi-1×pi ,i=1,2,…,n),如何确定计算矩阵连乘积A1A2…An的一个计算次序(完全加括号方式),使得依此次序计算矩阵连乘积需要的数乘次数最少。

    输入数据第一行为矩阵个数,第二行为n+1个数字a[0~n],其中对于第i个矩阵其大小为a[i-1]*a[i]。

    刚刚学习了区间DP,写发题解纪念一下。

    按照区间DP的思想,可以倒着分析,枚举最后一次进行乘法的位置,将原区间转化为两个子区间,相应代表了将原问题转化为两个规模较小的子问题。这里可以将递归和记忆化结合起来,递归的终点就是区间左端点等于右端点,由于提前给dp[i][i]赋值为0,所以这里直接return 0;同时如果dp[l][r]不为初始化时的0x3f3f3f3f的话说明这个值已经得到了就不用再算一遍了,直接return就好(记忆化)。然后就是dp[l][r]还没被计算过,那么枚举每个可能为当前区间最后一次做乘法的位置:l~r-1,然后写转移方程dp[l][r]=min(dp[l][r],process(l,i)+process(i+1,r)+a[l-1]*a[i]*a[r])(注意这里的dp[l][r]不要写成process(l,r)要不然永远无法更新,直接死循环了),至于为啥加的是a[l-1]*a[i]*a[r],这是根据矩阵乘法的性质得来的,分开的左半个矩阵的大小为a[l-1]*a[i],右半个矩阵的大小为a[i]*a[r],算出来后直接return即可。最终要求的就是process(1,n)。

    #include <bits/stdc++.h>
    using namespace std;
    int n,a[1005];//第i个矩阵是a[i-1]*a[i]大小 
    int dp[1005][1005]={0};
    int process(int l,int r)
    {
        if(dp[l][r]!=0x3f3f3f3f)return dp[l][r];
        int i;
        for(i=l;i<r;i++)
        {
            dp[l][r]=min(dp[l][r],process(l,i)+process(i+1,r)+a[l-1]*a[i]*a[r]);//这里的dp[l][r]不要写成process(l,r)要不然永远无法更新,直接死循环了 
        }
        return dp[l][r];
    }
    int main()
    {
        cin>>n;
        int i;
        for(i=0;i<=n;i++)scanf("%d",&a[i]);
        memset(dp,0x3f3f3f3f,sizeof(dp));
        for(i=1;i<=n;i++)dp[i][i]=0;
        printf("%d",process(1,n));
        return 0;
    }
  • 相关阅读:
    升级windows 11小工具
    windows 10更新升级方法
    您需要了解的有关 Oracle 数据库修补的所有信息
    Step by Step Apply Rolling PSU Patch In Oracle Database 12c RAC Environment
    Upgrade Oracle Database Manually from 12.2.0.1 to 19c
    如何应用版本更新 12.2.0.1.210420(补丁 32507738 – 2021 年 4 月 RU)
    xtrabackup 安装、备份和恢复
    Centos_Lvm expand capacity without restarting CentOS
    Centos_Lvm_Create pv vg lv and mount
    通过全备+relaylog同步恢复被drop的库或表
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/12506902.html
Copyright © 2011-2022 走看看