矩阵连乘积 ZOJ 1276 Optimal Array Multiplication Sequence

时间:2023-03-08 22:01:21

题目传送门

 /*
题意:加上适当的括号,改变计算顺序使得总的计算次数最少
矩阵连乘积问题,DP解决:状态转移方程:
dp[i][j] = min (dp[i][k] + dp[k+1][j] + p[i-1] * p[k] * p[j]) (i<=k<j)
s[i][j] 记录断开的地方(即加括号的位置),回溯法输出结果
*/
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <iostream>
using namespace std; const int MAXN = 1e2 + ;
const int INF = 0x3f3f3f3f;
int dp[MAXN][MAXN];
int s[MAXN][MAXN];
int p[MAXN];
int n; void print(int i, int j)
{
if (i == j) printf ("A%d", i);
else
{
printf ("(");
print (i, s[i][j]);
printf (" x ");
print (s[i][j] + , j);
printf (")");
}
} void work(void)
{
for (int i=; i<=n; ++i) dp[i][i] = ;
for (int l=; l<=n; ++l)
{
for (int i=; i<=n-l+; ++i)
{
int j = i + l - ;
dp[i][j] = INF;
for (int k=i; k<=j-; ++k)
{
int tmp = dp[i][k] + dp[k+][j] + p[i-] * p[k] * p[j];
if (tmp < dp[i][j])
{
dp[i][j] = tmp; s[i][j] = k;
}
}
}
} print (, n); puts ("");
} int main(void) //ZOJ 1276 Optimal Array Multiplication Sequence
{
//freopen ("ZOJ_1276.in", "r", stdin); int cas = ;
while (scanf ("%d", &n) == )
{
if (n == ) break;
for (int i=; i<=n; ++i) scanf ("%d%d", &p[i-], &p[i]); printf ("Case %d: ", ++cas);
work ();
} return ;
} /*
Case 1: (A1 x (A2 x A3))
Case 2: ((A1 x A2) x A3)
Case 3: ((A1 x (A2 x A3)) x ((A4 x A5) x A6))
*/