最基本的矩阵链乘。
一开始打错一个字母WA了N次,郁闷,打印路径的时候找到一条最佳路径不要忘记return。
递推式子为:
dp[i][j] = min(dp[i][k] + dp[k + 1][j] + mat[i].x * mat[k].y * mat[j].y);
348 | Optimal Array Multiplication Sequence | Accepted | C++ | 0.066 | 2014-08-06 10:29:02 |
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<map>
#include<stack>
#include<queue>
#include<set>
#include<ctime>
#include<cmath>
#include<string>
#include<iomanip>
#include<climits>
#include<cctype>
#include<deque>
#include<list>
#include<sstream>
#include<vector>
#include<cstdlib>
using namespace std;
#define _PI acos(-1.0)
#define INF (1 << 30)
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> pill;
/*======================================
矩阵链乘问题,d[i][j]代表i ~ j 编号内矩形相乘最小次数
======================================*/
#define MAXD 10 + 10
int n,Case = 1;
int dp[MAXD][MAXD];
struct Mat{
int x;
int y;
}mat[MAXD];
void init(){
for(int i = 1 ; i <= n ; i++){
scanf("%d%d",&mat[i].x,&mat[i].y);
}
for(int i = 1 ; i <= n ; i++)
for(int j = i; j <= n ; j++)
if(i == j)
dp[i][j] = 0;
else
dp[i][j] = INF;
return;
}
void print(int i,int j){
if(i == j){
printf("A%d",i);
return ;
}
else
for(int k = i ; k < j ; k++)
if(dp[i][j] == dp[i][k] + dp[k + 1][j] + mat[i].x * mat[j].y * mat[k].y){
printf("(");print(i,k);printf(" x ");print(k + 1, j);printf(")");
return ;
}
return ;
}
void DP(){
init();
for(int j = 1 ; j <= n ; j++){
for(int i = 1 ; i + j <= n ; i++){
for(int k = i ; k < i + j ; k++)
dp[i][i + j] = min(dp[i][i + j],dp[i][k] + dp[k + 1][i + j] + mat[i].x * mat[i + j].y * mat[k].y);
}
}
printf("Case %d: ",Case++);
print(1,n);
printf("\n");
return ;
}
int main(){
while(scanf("%d",&n) && n){
DP();
}
return 0;
}