矩阵链乘的问题,好像很多算法书上讲DP都是开始就将矩阵链乘。这个题不是要求最小的运算量,而是求最优的方案是什么,难就难在了递归的输出,如何记录路径,如何输出。
我也是参看了别人的代码。递归输出。不过这个转移方程还是蛮好找的。dp[i][j] = min ( dp[i][k], dp[k + 1][j], p[i - 1]p[k]p[j] ).
// File Name: UVa348.cpp
// Author: Toy
// Created Time: 2013年04月15日 星期一 19时03分31秒
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cctype>
#include <cmath>
#include <string>
#include <algorithm>
#include <cstdlib>
#include <iomanip>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <utility>
#include <bitset>
#define L(x) x << 1
#define R(x) x << 1 | 1
using namespace std;
int num, path[15][15], p[15], dp[15][15], Case, tmp;
void output ( int i, int j ) {
if ( i == j ) printf ( "A%d", i );
else {
printf ( "(" );
output ( i, path[i][j] );
printf ( " x " );
output ( path[i][j] + 1, j );
printf ( ")" );
}
}
void DP ( ) {
for ( int d = 2; d <= num; ++d ) {
for ( int i = 1, j = d; j <= num; ++i, ++j ) {
dp[i][j] = 10000000000;
for ( int k = i; k < j; ++k ) {
tmp = dp[i][k] + dp[k + 1][j] + p[i - 1] * p[j] * p[k];
if ( dp[i][j] > tmp ) dp[i][j] = tmp, path[i][j] = k;
}
}
}
}
int main ( ) {
Case = 0;
while ( scanf ( "%d", &num ) != EOF && num ) {
for ( int i = 1; i <= num; ++i )
scanf ( "%d%d", &p[i - 1], &p[i] );
memset ( dp, 0, sizeof ( dp ) );
memset ( path, 0, sizeof ( path ) );
DP ( );
printf ( "Case %d: ", ++Case );
output ( 1, num );
printf ( "\n" );
}
return 0;
}