题目大意:给你一些矩阵,你要写一个程式来决定该如何相乘的顺序,使得用到乘法的次数会最少。
思路:最优矩阵链乘问题,典型的动态规划题目。
该问题的子问题为“把Ai,Ai+1,……,Aj乘起来需要多少次乘法”,如果用dp(i,j)表示这个问题的子问题的值,
则状态转移方程:dp(i,j) = min{dp(i,k) + dp(k+1,j) + row(i)*col(k)*col(j)}
row代表当前矩阵的行,col代表当前矩阵的列。
思路:最优矩阵链乘问题,典型的动态规划题目。
该问题的子问题为“把Ai,Ai+1,……,Aj乘起来需要多少次乘法”,如果用dp(i,j)表示这个问题的子问题的值,
则状态转移方程:dp(i,j) = min{dp(i,k) + dp(k+1,j) + row(i)*col(k)*col(j)}
row代表当前矩阵的行,col代表当前矩阵的列。
总结:由于dp[i][j]的初始条件没有写好,结果wa了很多次,没考虑全,以为dp[i][j],初始化为0就好了。
#include <cstdio>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 15;
struct Matrix {
int row,col;
}mat[N];
int dp[N][N], path[N][N];
void print_path(int l,int r) {
if(l == r) {
printf("A%d",l+1);
return ;
}else {
printf("(");
print_path(l,path[l][r]);
printf(" x ");
print_path(path[l][r]+1,r);
printf(")");
}
}
int main() {
int n , cas = 1;
while(scanf("%d",&n) != EOF && n) {
for(int i = 0; i < n; i++) {
scanf("%d%d", &mat[i].row, &mat[i].col);
}
memset(dp,0,sizeof(dp));
memset(path,0,sizeof(path));
for(int len = 1; len < n; len++) { //枚举长度
for(int i = 0; i < n - len; i++) { //枚举起点
int j = i + len;
dp[i][j] = dp[i][i] + dp[i+1][j] + mat[i].row * mat[i].col * mat[j].col;
path[i][j] = i;
for(int k = i+1; k < j; k++) { //枚举中断点
int tmp = dp[i][k] + dp[k+1][j] + mat[i].row * mat[k].col * mat[j].col;
if(tmp < dp[i][j]) {
dp[i][j] = tmp;
path[i][j] = k;
}
}
}
}
printf("Case %d: ",cas++);
print_path(0,n-1);
printf("\n");
}
return 0;
}