最优矩阵链乘。
思路:根据王晓东的教材上的讲解来写的,DP入门题,最优子结构怎么来的,重叠子问题等等。个人认为思想更加比方法更加重要。
状态转移方程:
d[i][j] = 0 (i == j)
d[i][j] = min{d[i][k]+d[k][j]+R[i-1]*C[k]*C[j]} (i < j && i<=k <j)
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
const int MAXN = 15;
const int INF = 0x3f3f3f3f;
int R[MAXN], C[MAXN];
int d[MAXN][MAXN];
int path[MAXN][MAXN];
int n;
int times;
void init()
{
memset(path, 0, sizeof(path));
}
int MatrixChain()
{
for(int i = 1; i <= n; i++) d[i][i] = 0;
for(int r = 2; r <= n; r++) //枚举链长
{
for(int i = 1; i <= n-r+1; i++) // j-i = r-1, j == n -> i <= n-r+1
{
int j = i+r-1; // j-i == r-1 -> j = i+r-1;
d[i][j] = d[i+1][j] + R[i]*C[i]*C[j]; // k == i;
path[i][j] = i;
for(int k = i; k < j; k++)
{
int t = d[i][k] + d[k+1][j] + R[i]*C[k]*C[j];
if(t < d[i][j])
{
d[i][j] = t;
path[i][j] = k;
}
}
}
}
return d[1][n];
}
int read_case()
{
init();
scanf("%d", &n);
if(!n) return 0;
for(int i = 1; i <= n; i++)
{
scanf("%d%d", &R[i], &C[i]);
}
return 1;
}
void print_ans(int i, int j)
{
if(i == j)
{
printf("A%d", i);
return ;
}
else
{
printf("(");
print_ans(i, path[i][j]);
printf(" x ");
print_ans(path[i][j]+1, j);
printf(")");
}
}
void solve()
{
int ans = MatrixChain();
printf("Case %d: ", ++times);
print_ans(1, n);
printf("\n");
}
int main()
{
times = 0;
while(read_case())
{
solve();
}
return 0;
}