您的位置:首页 > 其它

DP--矩阵连乘

2015-11-08 10:58 399 查看
问题:给定n个矩阵,求乘法次数的最小值

1)最优子结构:

一个简单的解决办法是把括号放在所有可能的地方,计算每个位置的成本,并返回最小值。对于一个长度为n的链,我们有n-1种方法放置第一组括号。

例如,如果给定的链是4个矩阵。让矩阵连为ABCD,则有3种方式放第一组括号:A(BCD),(AB)CD和(ABC)D。

所以,当我们把一组括号,我们把问题分解成更小的尺寸的子问题。因此,这个问题具有最优子结构性质,可以使用递归容易解决。
2)重叠子问题

以下是递归的实现,只需用到上面的最优子结构性质

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 50;
int p[maxn], d[maxn][maxn];

int chain(int i, int j)
{
if(i == j) return 0;
if(d[i][j] > 0) return d[i][j];
int ans = 0x3f3f3f3f;
for(int k=i; k<j; k++)
ans = min(ans, chain(i, k)+chain(k+1, j)+p[i-1]*p[k]*p[j]);
return d[i][j] = ans;
}

int main()
{
int n;
while(~scanf("%d", &n)) {
for(int i=0; i<=n; i++) scanf("%d", &p[i]);
memset(d, 0, sizeof(d));
printf("%d\n", chain(1, n));
}
return 0;
}


实际上是把矩阵乘法区间拆分,下面是迭代写法:这里只给出dp函数部分,其余同上

int chain(int n)
{
for(int div=2; div<=n; div++) {
for(int i=1; i<=n-div+2; i++) {
int j = i + div - 1;
d[i][j] = 0x3f3f3f3f;
for(int k=i; k<j; k++)
d[i][j] = min(d[i][j], d[i][k]+d[k+1][j]+p[i-1]*p[k]*p[j]);
}
}
return d[1]
;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: