矩阵连乘 /// 区间DP oj1900

题目大意:
输入t ;t为测试用例个数
接下来t个测试 每个测试用例
第一行输入n; n为矩阵个数 保证n个矩阵依序是可乘的
接下来n行 每行输入p,q;p为长度q为宽度
对给定的n个矩阵确定一个计算次序使得总的乘法次数最少
并输出该最优值
Sample Input

1
4
50 10
10 40
40 30
30 5

Sample Output

10500

理论讲解

https://www.cnblogs.com/Jason-Damon/p/3231547.html

https://blog.csdn.net/wangmengmeng99/article/details/50134673

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
int a[55],dp[55][55];
//int pre[55][55];
// /* pre[i][j]=k 即 i到j之间由k断开
// 借此输出最小乘数的表达式 */
//void print_chain(int i, int j)
//{    // 递归输出最小连乘的表达式
//    if (i==j) printf("矩阵%d",i);
//    else
//    {
//        printf("(");
//        print_chain(i,pre[i][j]);
//        printf("*");
//        print_chain(pre[i][j]+1,j);
//        printf(")");
//    }
//}
int main()
{
    int t;
    while(~scanf("%d",&t))
    {
        while(t--)
        {
            int n; scanf("%d",&n);
            for(int i=1;i<=n;i++)
            {
                int p,q; scanf("%d%d",&p,&q);
                if(i==1) a[0]=p;  a[i]=q;
            } // 第一个存行和列 之后的只存列

            //memset(pre,0,sizeof(pre));
            memset(dp,INF,sizeof(dp)); // 初始化无穷大
            for(int i=1;i<=n;i++) dp[i][i]=0;
            /// 只有本身一个矩阵时 矩阵乘积为0

            for(int i=2;i<=n;i++) /// 枚举矩阵个数 由从小推大
                for(int l=1;l<=n-i+1;l++) /// 枚举左端下标
                {
                    int r=l+i-1; // 根据个数 得到右端下标
                    dp[l][r]=dp[l+1][r]+a[l-1]*a[l]*a[r];
                    /// dp[l][r]视为 l矩阵*(dp[l+1][r])矩阵
                    //pre[l][r]=l;

                    for(int k=l+1;k<r;k++)
                        dp[l][r]=min(dp[l][r],
                        dp[l][k]+dp[k+1][r]+a[l-1]*a[k]*a[r]);
                    /// dp[l][r]视为 (dp[l][k])矩阵*(dp[k+1][r])矩阵
                    
                    // 当需要记录 pre[][] 时
//                    {
//                        int tmp=dp[l][k]+dp[k+1][r]+a[l-1]*a[k]*a[r];
//                        if(tmp<dp[l][r]) dp[l][r]=tmp, pre[l][r]=k;
//                    }
                }
//            for(int i=1;i<=n;i++)
//            {
//                for(int j=1;j<=n;j++)
//                    printf("%d ",pre[i][j]);
//                // printf("%d ",dp[i][j]);
//                printf("
");
//            }
//            print_chain(1,n); // 最小连乘表达式
//            printf("
");
            printf("%d
",dp[1][n]); // 最小连乘次数
        }
    }

    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zquzjx/p/9094013.html