算法导论C 矩阵连乘(动态规划)

题目:

题目描述

给定n个矩阵{A1,A2,...,An},及m个矩阵连乘的表达式,判断每个矩阵连乘表达式是否满足矩阵乘法法则,如果满足,则计算矩阵的最小连乘次数,如果不满足输出“MengMengDa“。

输入

输入数据由多组数据组成(不超过10组样例)。每组数据格式如下:
第一行是2个整数n (1≤n≤26)和m(1≤m≤3),表示矩阵的个数。
接下来n行,每行有一个大写字母,表示矩阵的名字,后面有两个整数r和c,分别表示该矩阵的行数和列数,其中1<r, c<100。
第n+1行到第n+m行,每行是一个矩阵连乘的表达式(2<=矩阵个数<=100)。

输出

对于每个矩阵连乘表达式,如果运算不满足矩阵乘法法则的情况(即左矩阵列数与右矩阵的行数不同),则输出“MengMengDa”,否则输出最小矩阵连乘次数。

数据保证结果不超过1e9。

样例输入 Copy
3 2
A 10 100
B 5 50
C 100 5
ACB
ABC
样例输出 Copy
7500
MengMengDa

解析:

用dp[i][j]数组表示第i个矩阵到第j个矩阵连乘所需最小连乘次数

用p[]数组存储每个矩阵的行数和列数,如果矩阵能够连乘,则第i个矩阵的列数=第i+1个矩阵的行数,所以只需要用n+1个数字就能存储n个矩阵的行数和列数

可以把需要计算的矩阵拆分成两半,等于左边子区间最小连乘次数+右边子区间最小连乘次数+左右两个子区间连接起来需要的连乘次数。

假设第i个矩阵到第j个矩阵从第k个矩阵分成两半,那么dp[i][j]=dp[i][i] + dp[i+1][j] + p[i-1]*p[i]*p[j]

由此,只需要遍历k找到最佳的拆分位置即可

代码:

#include<iostream>
using namespace std;
int dp[110][110];
int p[110];
struct jz{
	int x,y;
}m[26];
void solve()
{
	string x;
	cin>>x;
	int size = x.size();
	p[0] = m[x[0]-'A'].x;
	for(int i=0;i<size-1;i++)
	{
		int a = x[i] - 'A';
		int b = x[i+1] - 'A';
		p[i+1] = m[a].y; 
		if(m[a].y!=m[b].x)
		{
			cout<<"MengMengDa"<<'\n';
			return;
		}
	}
	
	p[size] = m[x[size-1]-'A'].y;
	for(int i=1;i<=size;i++)//初始化,单个矩阵 
		dp[i][i] = 0;
	for(int r=2;r<=size;r++)//r个矩阵连乘 
	{
		for(int i=1;i<=size-r+1;i++)//以第i个矩阵开头 
		{
			int j = i+r-1;//以第j个矩阵结尾
			dp[i][j] = dp[i][i] + dp[i+1][j] + p[i-1]*p[i]*p[j];
			for(int k=i+1;k<j;k++)
			{
				int t = dp[i][k] + dp[k+1][j] + p[i-1]*p[k]*p[j];
				if(t<dp[i][j])
					dp[i][j] = t;
			} 
		}
	}
	cout<<dp[1][size]<<'\n';
}
int main()
{
	int n,mm;
	while(cin>>n>>mm)
	{
		for(int i=0;i<n;i++)
		{
			char name;
			int x,y;
			cin>>name>>x>>y;
			m[name-'A'].x = x;
			m[name-'A'].y = y;
		}
		while(mm--)
			solve();
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

owooooow

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值