UVA - 348 Optimal Array Multiplication Sequence (最优矩阵连乘)

题目大意:给你一些矩阵,你要写一个程式来决定该如何相乘的顺序,使得用到乘法的次数会最少。

思路:最优矩阵链乘问题,典型的动态规划题目。
该问题的子问题为“把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;
}

你可能感兴趣的:(array,uva,Optimal,Multip,348)