紫书第九章-----动态规划初步(最优矩阵链乘)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ccnuacmhdu/article/details/81479311

最优矩阵链乘

这里写图片描述
上面说的计算量其实是乘法的计算量,并没有关注加法!因为加法的计算量,加法其实是和乘法相关的,乘法越少,加法也就越少
【分析】
结合《算法竞赛入门经典(第2版)》分析,突破点是最后一次乘法!不妨设Ai到Aj矩阵相乘,最后一次乘法的前k个矩阵之积和后面的矩阵之积相乘。row[i],col[i]表示第i个矩阵的行和列。那么,

状态:dp[i][j]表示Ai到Aj矩阵相乘的最小计算量
状态转移:dp[i][j]=min{dp[i][k]+dp[k+1][j]+row[i]*col[k]*col[j]}

Optimal Array Multiplication Sequence UVA - 348

#include<iostream>
#include<cstring>
using namespace std;

const int maxn=15;
const int INF=(1<<30);

int n;
int row[maxn],col[maxn];
int kase=0;
int d[maxn][maxn];
int path[maxn][maxn];

int dp(int i,int j){
    int &ans=d[i][j];
    if(ans!=-1) return ans;
    ans=INF;
    for(int k=i;k<j;k++){
        //用tmp接收一下,不要把这个写到if语句里面判断,减少递归调用时间消耗
        int tmp=dp(i,k)+dp(k+1,j)+row[i]*col[k]*col[j];
        if(ans>tmp){
            ans=dp(i,k)+dp(k+1,j)+row[i]*col[k]*col[j];
            path[i][j]=k;
        }
    }
    return ans;
}

void print(int i,int j){
    if(i==j){
        cout<<"A"<<i;
        return ;
    }
    cout<<"(";
    for(int k=1;k<j;k++){
        if(path[i][j]==k){
            print(i,k);
            cout<<" x ";//这两个空格也是坑
            print(k+1,j);
            break;
        }
    }
    cout<<")";
}

int main()
{
    while(cin>>n && n){
          for(int i=1;i<=n;i++){
                cin>>row[i]>>col[i];
          }
          memset(d,-1,sizeof(d));
          for(int i=1;i<=n;i++) d[i][i]=0;
          dp(1,n);
          cout<<"Case "<<++kase<<": ";
          print(1,n);
          cout<<endl;
    }
    return 0;
}

Multiplication Puzzle POJ - 1651

【分析】
这道题也是最优矩阵链乘,直接用上题的代码,稍微修改一下即可

#include<iostream>
#include<cstring>
using namespace std;

const int maxn=105;
const int INF=(1<<30);

int n;
int row[maxn],col[maxn];
int d[maxn][maxn];
int a[maxn];

int dp(int i,int j){
    int &ans=d[i][j];
    if(ans!=-1) return ans;
    ans=INF;
    for(int k=i;k<j;k++){
        ans=min(dp(i,k)+dp(k+1,j)+row[i]*col[k]*col[j],ans);
    }
    return ans;
}

int main()
{
    while(cin>>n){
          for(int i=1;i<=n;i++){
                cin>>a[i];
          }
          for(int i=1;i<=n-1;i++){
                row[i]=a[i];
                col[i]=a[i+1];
          }
          memset(d,-1,sizeof(d));
          for(int i=1;i<=n;i++) d[i][i]=0;
          cout<<dp(1,n-1)<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ccnuacmhdu/article/details/81479311
今日推荐