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 = 6000the 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 ];
然后就可以得到我们的状态转移方程:
即对与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]);
}
}