应用动态规划算法的最优子结构性质和子问题重叠性质求解此问题。分析动态规划算法的基本思想,应用动态规划策略写出算法及相应的程序,求解此题。要读懂读透A[i,j],A[1,n]=A[1,k] ×A[k+1,n],m[i][j],s[i][j]各式所表达的含义并正确加以应用。m[i][j]的递归定义:C语言
时间: 2023-09-18 13:08:04 浏览: 58
动态规划算法的基本思想是将原问题分解成若干个子问题,先求解子问题,然后利用子问题的解构造出原问题的解。
对于矩阵连乘问题,我们可以定义一个二维数组A来表示矩阵连乘的最小代价,其中A[i,j]表示从第i个矩阵到第j个矩阵的最小代价。同时,我们可以定义两个二维数组m和s,其中m[i,j]表示从第i个矩阵到第j个矩阵的最小代价,s[i,j]表示从第i个矩阵到第j个矩阵的最小代价的断点。
根据题目中的最优子结构性质和子问题重叠性质,我们可以得到矩阵连乘问题的动态规划转移方程:
A[i,j] = min{A[i,k] + A[k+1,j] + p[i-1]*p[k]*p[j]},其中i ≤ k < j
m[i,j] = A[i,j],当i=j时,m[i,j]=0
s[i,j] = k,其中i ≤ k < j,且A[i,j]=A[i,k]+A[k+1,j]+p[i-1]*p[k]*p[j]
接下来,我们可以根据上述转移方程编写求解矩阵连乘问题的动态规划算法程序:
```c
#include <stdio.h>
#include <stdlib.h>
#define MAX_N 100
void matrixChainOrder(int* p, int n, int m[MAX_N][MAX_N], int s[MAX_N][MAX_N]) {
for (int i = 1; i <= n; i++) {
m[i][i] = 0;
}
for (int l = 2; l <= n; l++) {
for (int i = 1; i <= n-l+1; i++) {
int j = i+l-1;
m[i][j] = INT_MAX;
for (int k = i; k < j; k++) {
int q = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j];
if (q < m[i][j]) {
m[i][j] = q;
s[i][j] = k;
}
}
}
}
}
void printOptimalParens(int s[MAX_N][MAX_N], int i, int j) {
if (i == j) {
printf("A%d", i);
} else {
printf("(");
printOptimalParens(s, i, s[i][j]);
printOptimalParens(s, s[i][j]+1, j);
printf(")");
}
}
int main() {
int p[MAX_N];
int n;
printf("请输入矩阵个数:");
scanf("%d", &n);
printf("请输入%d个矩阵的行列数(如A1为2x3,则输入2 3):\n", n);
for (int i = 0; i <= n; i++) {
int row, col;
scanf("%d %d", &row, &col);
p[i] = row;
}
p[n] = col;
int m[MAX_N][MAX_N];
int s[MAX_N][MAX_N];
matrixChainOrder(p, n, m, s);
printf("最小代价为:%d\n", m[1][n]);
printf("最优加括号方案为:");
printOptimalParens(s, 1, n);
printf("\n");
return 0;
}
```
在程序中,我们使用了两个函数matrixChainOrder和printOptimalParens。其中,matrixChainOrder函数用于求解矩阵连乘的最小代价,并计算出每次计算的断点;printOptimalParens函数用于输出最优加括号方案。
需要注意的是,在编写程序时,需要将矩阵的行列数作为输入,因此我们在输入矩阵行列数时,需要输入n+1个数,其中第i个数表示第i个矩阵的行数,第i+1个数表示第i个矩阵的列数。同时,我们还需要在程序中包含头文件<stdlib.h>和<limits.h>,以使用INT_MAX宏定义。
阅读全文