UVA 348 Optimal Array Multiplication Sequence

最优矩阵链乘。

思路:根据王晓东的教材上的讲解来写的,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;
}


你可能感兴趣的:(UVA 348 Optimal Array Multiplication Sequence)