http://cdn.ac.nbutoj.com/Problem/view.xhtml?id=1003&&矩阵链乘

  • 问题描述
  • 给定一个有n个矩阵的矩阵链A1A2A3…An,其中矩阵Ai(i=1,2,3…n)的维度为pi-1*pi。我们知道,两个维度分别为m*r和r*n的矩阵用一般的矩阵乘法相乘,所需的运算次数为m*r*n,最后得到一个维度为m*n的结果矩阵。对于矩阵链问题,因为矩阵乘法具有结合律,其运算顺序有很多中选择。换句话说,不论如何括号其乘积,最后结果都会是一样的。例如,若有四个矩阵A、B、C和D,将可以有:

    (ABC)D = (AB)(CD) = A(BCD) = A(BC)D = ...
    

    但括号其乘积的顺序会影响到需要计算乘积所需简单算术运算的数目,即其效率。例如,设A为一10*30矩阵,B为30*5矩阵与C为5*60矩阵,则:

    (AB)C有(10*30*5) + (10*5*60) = 1500 + 3000 = 4500 个运算
    A(BC)有(30*5*60) + (10*30*60) = 9000 + 18000 = 27000 个运算
    ...
    

    明显地,第一种方式要有效多了。所以,矩阵链乘法问题也就是如何对矩阵乘积加括号,使得它们的乘法次数达到最少。


  • 输入
  • 输入的第一行为一个正整数n(1<=n<=200)。表示矩阵的个数。
    输入的第二行包含n+1个整数,分别表示pi(0<=i<=n),其中每个pi在[1,200]范围内。
  • 输出
  • 输出一个整数表示最少要进行的乘法次数。
  • 样例输入
  • 3
    1 2 3 4
    3
    10 30 5 60
    
  • 样例输出
  • 18
    4500
    
    属于动态规划题,其实也可以看做是一道贪心题,通过求出局部最优,从而得到全局最优,下面给出动态转移方程:
    dp[i][j]:表示矩阵从i到j链乘需要的最小次数;s[i-1]为i矩阵的行数,s[i]为i矩阵的列数。如果i=j;dp[i][j]=0;否者dp[i][j]=max(dp[i][k]+dp[k+1][j]+s[i-1]*s[k]*s[j]);
    AC代码:
    #include<iostream>
    #include<string.h>
    #define N 205
    using namespace std;
    int s[N];
    int  dp[N][N];
    int slove(int n)
    {   
    	int i;
    	for(i=1;i<=n;++i)
    		dp[i][i]=0;
    	 for(int k=2;k<=n;++k)
    	 {
    		 for(int j=1;j<=n-k+1;++j)
    		 {
    			 i=j+k-1;
    			 dp[j][i]=999999999;
    			 
    			 for(int r=j;r<i;++r)
    				 dp[j][i]=min(dp[j][i],(dp[j][r]+dp[r+1][i]+s[j-1]*s[r]*s[i]));
    		 }
    	 }
    	 return dp[1][n];
    }
    int main()
    {   
    	int n;
    	while(cin>>n)
    	{
    		for(int i=0;i<=n;++i) cin>>s[i];
    		cout<<slove(n)<<endl;
    	}return 0;
    }
    


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值