题意:给你几个矩阵相乘, 然你求出最少计算次数时矩阵相乘的表达式
题目地址:
这道题的本意就是让你求矩阵相乘时的最少计算次数, 并输出最少计算时的计算路径。我们只要在dp时用一个数组保存路径, 最后递归输出即可。
状态:dp(i,k )表示第i个矩阵到第j个矩阵的最少计算次数,
状态转移方程: dp[i][[k] = min(dp[i][j] + dp[j+1][k] + sux[i]*suy[j]*suy[k])
具体解释看代码注释
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 20;
int sux[maxn], suy[maxn], dp[maxn][maxn], d[maxn][maxn]; //sux表示矩阵的行,suy表示矩阵的列,dp[i][k]表示矩阵i到矩阵k的最少计算次数,d记录路径
//路径输出
void print(int x, int y)
{
if(x == y)
{
printf("A%d", x+1);
return;
}
printf("(");
print(x, d[x][y]);
printf(" x ");
print(d[x][y]+1, y);
printf(")");
}
int main()
{
int n, count = 0;
while(scanf("%d", &n), n)
{
for(int i = 0; i < n; i++)
scanf("%d%d", &sux[i], &suy[i]);
memset(dp, 99, sizeof(dp)); //初始化dp数组, 赋足够大的数
for(int i = 0; i < n; i++) //当表示一个矩阵时,次数为零
dp[i][i] = 0;
for(int k = 1; k < n; k++) //枚举链乘的长度
for(int i = 0; i < n-k; i++) //求链乘长度为k时链乘的最少次数
for(int j = i; j < i+k; j++) //枚举链乘长度为k时最后一次链乘的位置
{
int temp = dp[i][j] + dp[j+1][i+k] + sux[i]*suy[j]*suy[i+k]; //记录当前位置的最少次数
if(temp < dp[i][i+k])//判断是否需要更新
{
dp[i][i+k] = temp;
d[i][i+k] = j;//更新的同时保存路径
}
}
printf("Case %d: ", ++count);
print(0, n-1);//递归输出路径
printf("\n");
}
return 0;
}