动态规划:矩阵链乘积

确定n个矩阵连乘积 A1A2A3…An 的计算次序,使得按照这一次序计算矩阵连乘积,需要的"数乘"次数最小。

思路:
递归定义 d p [ i , j ] dp[i,j] dp[i,j]如下:
对于i=j时的平凡问题,矩阵链只包含唯一的矩阵 A i A_i Ai,因此不需要做任何标量乘法运算。所以,对所有i=1,2,…,n, d p [ i , i ] = 0 dp[i,i]=0 dp[i,i]=0
若i<j,我们利用步骤1中得到的最优子结构来计算m[i,j]。
我们假设A(i)A(i+1)…A(j)的最优括号化方案的分割点在矩阵A(k)和A(k+1)之间,其中i<=k<j。
那么, d p [ i , j ] dp[i,j] dp[i,j]就等于计算A(i…k)和A(k+1…j)的代价加上两者相乘的代价的最小值。
由于矩阵Ai的大小为x*y,易知A(i…k)和A(k+1…j)相乘的代价为 A i x ∗ A k y ∗ A j y A_ix*A_ky*A_jy AixAkyAjy次标量乘法运算。
因此,我们得到 d p [ i , j ] = d p [ i , k ] + d p [ k + 1 , j ] + A i x ∗ A k y ∗ A j y dp[i,j]=dp[i,k]+dp[k+1,j]+ A_ix*A_ky*A_jy dp[i,j]=dp[i,k]+dp[k+1,j]+AixAkyAjy
此公式假定最优分割点k是已知的,但实际上我们不知道。
但k只有j-i种可能的取值,即k=i,i+1,…,j-1。
由于最优分割点必在其中,我们只需检查所有可能情况,找到最优者即可。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f;
int main()
{
    int t;cin>>t;
    while(t--){
        ll dp[101][101];
        memset(dp,INF,sizeof(dp));
        int n;cin>>n;
        struct Node{int x,y;}stu[n];
        for(int i=0;i<n;i++) cin>>stu[i].x>>stu[i].y;
        for(int i=0;i<n;i++) dp[i][i]=0;
        //链长度
        for(int len=1;len<n;len++){
        //矩阵头
            for(int i=0;i+len<n;i++){
            //矩阵尾
                int j=i+len;
                for(int k=i;k<j;k++){
                    dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+stu[i].x*stu[k].y*stu[j].y);
                }
            }
        }
        cout<<dp[0][n-1]<<endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值