(JZ1192)2018.07.06【2018提高组】模拟C组 0. 矩阵【推荐】

1192.矩阵【推荐】 (Standard IO)

Description

N(2<=N<=500)个矩阵相乘,求进行乘法的最少次数,我们认为两个矩阵A(m*n)*B(n*p)的乘法次数为m*n*p次。

Input

第一行是整数N,接下来N行是对每个矩阵的描述,一行两个整数a,b,(1<=a,b<=50)a表示行,b表示列。输入确保能够相乘。

Output

一行输出最少乘法次数。

Sample Input

3
50 10
10 20
20 5

Sample Output

3500

Data Constraint

题解:

   本题涉及知识点为,矩阵乘法的性质:A*B=C,C行=A行,C列=B列。例:(10*20)*(20*5)=(10*5);矩阵乘法不满足交换律,满足结合律和分配律ヾ(o◕∀◕)ノヾ
   本题可以使用DP或者记忆化搜索来完成。f[i,j]表示从第i个矩阵相乘到第j个矩阵的最小乘法次数。
   至于是如何将最小乘法次数求出来,用样例来说明,如果按顺序相乘,是A1*A2*A3。这么算出来的是15000,不符合样例输出。┑( ̄Д  ̄)┍那么要如何处理样例呢?
   样例输出是用了乘法结合律,将式子分成两个部分,变为A1*(A2*A3),算出来就是3500了 \(^o^)/YES!
   我们再举一个例子:A*B*C*D.那么它可以分成(A*B*C)D,其中还可以再细分!将”A*B*C”分成两个部分,变为A(B*C),从而变为[A*(B*C)]*D.在这里,我们可以用记忆化搜索来实现它

#include<iostream>
#include<vector>
using namespace std;
int f[505][505],a[505];
int try(int i, int j){
        if(i == j) return 0;
        if(f[i][j] > 0)  return f[i][j];//若已求出最小值,就不用再求了
        int num = 0xffffff;
        for(int k = i; k < j; k++)//细分结合律
                num=min(num,try(i,k)+try(k+1,j)+a[i-1]*a[k]*a[j]);//num=两个部分本身的最小值+两部分相乘的乘法次数
        f[i][j]=num;
        return num;
}
int main(){
        int n,i,j;
        cin>>n;
        for(i=0; i<n; i++)
            cin >>a[i]>>a[i+1];               
        for(i=0; i<=100; i++)
            for(j=0; j<=100;j++)
                f[i][j] = 0;
        cout << try(1, n) << endl;
        return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值