TZOJ矩阵链乘法

 


TZOJ 4299 

题目:

If we are given a sequence of matrices to multiply, A1, A2, A3, ..., An, we can multiply them in any order, since matrix multiplication is associative, to generate the product.
If we have three matrices A1, A2 and A3. The product can be generated in two ways, A1(A2A3) or (A1A2)A3.

The cost of multiplying a nxm by an mxp matrix is nxmxp So the choice of parenthesis could affect the cost of multiplying a sequence of matrices.

For example, if we have the matrices A1, a 5 x 50 matrix, A2, a 50 x 10 matrix and A3, a 10 x 8 matrix, the cost of A1(A2A3) would be:
(A2A3) 50 x 10 x 8 = 4000, a resulting 50 x 8 matrix
A1(A2A3) 5 x 50 x 8 = 2000, a resulting 5 x 8 matrix
Total Cost = 4000 + 2000 = 6000

the cost of (A1A2)A3 would be:
(A1A2) 5 x 50 x 10 = 2500, a resulting 5 x 10 matrix
(A1A2)A3 5 x 10 x 8 = 400, a resulting 5 x 8 matrix
Total Cost = 2500 + 400 = 2900

输入:

The input data will contain multiple cases. Each case will contain a matrix chain is represented by a series of positive integers, p, 0 < p <= 100, terminated by a 0. For example the chain above would be “5 50 10 8 0". Note that N matrices are represented by N + 1 non-zero numbers. 2 <= N <= 10.

 

输出:

The output data will contain the lowest and highest cost of multiplying the matrix chain, in that order, separated by a single space. The highest cost will not exceed 2000000000.

样例输入:

5 50 10 8 0
4 12 6 9 12 0
25 30 10 5 0

样例输出:

2900 6000
936 2520
5250 8750


开始我写的是暴力递归(心想n才10),仔细一捋,复杂度为o(n!) 大致口胡一下300多万加多组的话TLE;

然后查阅百度后写下这个博客(发现是个矩阵链乘法),捋一捋DP的基本思想(菜鸡自己写着玩);

 

下面自己来捋捋思路:

令一个data数组保存N+1个数字,MIN [ i ] [ j ] 的意义为 Ai * Ai + 1 *.....*  Aj的最小费用,MAX [ i ] [ j ]--------,F [ i ][ j ]----------;

首先,A1*A2=data[ 0 ] *data[ 1 ] * data[ 2 ] ;

再加长一个长度,有A1* A2 *A3 =A1*(A2*A3)    或者(A1*A2)*A3 ;

其中的(A2*A3)与 (A1*A2)是可以在表中得到的;

观察可知 A1* A2 *A3 =A1*(A2*A3)= data[ 0 ]*data[ 1 ] * data[ 3 ] + F(A2*A3) +F(A1);

基本上到这就可以得出一个

F(A1*A2*.......*An)=F(A1*A2*......*Ap)+F(Ap+1*......*An)+data[ 0] * data[ p ] * data [ n ];

然后就可以得到我们的状态转移方程:

F[ i ] [ j ] = \left\{\begin{matrix} 0& i=j\\ F[i][p]+F[p+1][j]+data[ 0] * data[ p ] * data [ j ] & i<=p <=j \end{matrix}\right.

 

即对与p  i  ~> j 循环就可以得到 一个 F[ i ] [ j ] 的一个费用 每次循环时 对他本身取 max(F[ i ][ j ],----------),min(F[ i ][ j ])

(注意赋初值);

AC代码:

#include<bits/stdc++.h>
using namespace std;
int MAX[11][11],MIN[11][11];
int data[11];
int main(){
	int a;
	while(scanf("%d",&data[0])!=EOF)
	{
		memset(MAX,0,sizeof(MAX));
		memset(MIN,0x7f,sizeof(MIN));
		for(int i=1;i<11;i++) //给i==j 情况赋上初值
                    MIN[i][i]=0;
		int n=0;
		while(scanf("%d",&data[++n]),data[n])
		for(int l=2;l<=n;l++) //链长为2到n
        {
            for(int j=n-l+1;j>0;j--)
		    {
		        int k=j+l-1;
		        for(int p=j;p<=k-1;p++)
                {
                    MAX[j][k]=max(MAX[j][k],MAX[j][p]+MAX[p+1][k]+data[j-1]*data[p]*data[k]);
                    MIN[j][k]=min(MIN[j][k],MIN[j][p]+MIN[p+1][k]+data[j-1]*data[p]*data[k]);
                }
		    }
        }
		printf("%d %d\n",MIN[1][n-1],MAX[1][n-1]);
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值