Cod sursa(job #458038)

Utilizator tomescu_alinTomescu Alin tomescu_alin Data 22 mai 2010 18:33:33
Problema Parantezare optima de matrici Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.65 kb
#include <cstring>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <fstream>

/**
 *	Matrix chain multiplication. Given n matrices A_1, A_2, ... A_n such that
 *	A_i has dimension d[i-1] and d[i], what is the optimal parenthesization
 *	that gives the minimum number of multiplications to compute the product
 *	A_1 * A_2 * ... * A_n?
 *
 *	Denote A(1, n) as the product of matrices 1 through n.
 *	To compute A(1, n) optimally we have to compute A(1, k) and A(k+1, n)
 *	optimally, for an optimal choice of k in [1, n-1].
 *
 *	Denote m[i][j] as the optimal cost of multiplying matrices i through j. Then,
 *		m[i][j] = min(i <= k < j) of { m[i][k] + m[k+1][j] + d[i-1]d[k]d[j] }
 *
 *	Base cases are m[i][i] = 0, multiplying matrices i through i requires no 
 *	computation. And m[i][i+1] = d[i-1]d[i]d[i+1], multiplying two matrices.
 */

using namespace std;

const unsigned int MAX_MATRICES = 500;

class MatrixChainMultiplication
{
	public:
		MatrixChainMultiplication(unsigned long long * dimensions, unsigned int numMatrices)
			:	dim(dimensions), n(numMatrices)
		{
			for(unsigned int i = 0; i <= MAX_MATRICES; i++)
			{
				for(unsigned int j = 0; j <= MAX_MATRICES; j++)
				{
					cost[i][j] = 0;
				}
			}
			
			for(unsigned int i = 0; i < MAX_MATRICES; i++)
			{
				cost[i][i+1] = dim[i-1]*dim[i]*dim[i+1];
			}
		}
		
	public:
		unsigned long long computeRecursive()
		{
			return recursive(1, n);;
		}
		
		unsigned long long computeIterative()
		{
			/**
			 *	Compute the optimal parenthesization of matrix products of
			 *	increasing sizes, starting at 3 (1 and 2 are trivial) and
			 *	going up to n, which will give you the solution.
			 *
			 *	So we'll compute cost[i, i + size], for i going up to n - size to stay
			 *	within bounds.
			 */
			for(unsigned int size = 2; size < n; size++)
			{
				for(unsigned int i = 1; i <= n - size; i++)
				{
					unsigned int j = i + size;
					
					cost[i][j] = ~0;
					for(unsigned int k = i; k < j; k++)
					{
						unsigned long long cost_mult = dim[i-1] * dim[k] * dim[j];
						unsigned long long current_cost = cost[i][k] + cost[k+1][j] + cost_mult;
						
						if(cost[i][j] > current_cost)
						{
							cost[i][j] = current_cost;
						}
					}
				}
			}
			
			return cost[1][n];
		}
		
	private:
		/**
		 *	Use caching for simple and easy implementation.
		 */
		unsigned long long recursive(unsigned int i, unsigned int j)
		{
			if(i == j)
				return 0;
			else if(cost[i][j])
				return cost[i][j];
			else
			{
				unsigned long long min_k = ~0;
				
				for(unsigned int k = i; k < j; k++)
				{
					unsigned long long current_cost, cost_ik, cost_kj, cost_mult;
					
					cost_mult = dim[i-1] * dim[k] * dim[j];
					
					cost_ik = recursive(i, k);
					cost_kj = recursive(k+1, j);
					
					current_cost = cost_ik + cost_kj + cost_mult;
					
					if(current_cost < min_k)
						min_k = current_cost;
				}
				
				cost[i][j] = min_k;
				
				return cost[i][j];
			}
		}
	
	private:
		unsigned long long * dim;
		unsigned int n;
		unsigned long long cost[MAX_MATRICES + 1][MAX_MATRICES + 1];
};

int main(int argc, char ** argv)
{
	const char * inFile = "podm.in";
	const char * outFile = "podm.out";
	
	ifstream fin(inFile);
	ofstream fout(outFile);
	
	/**
	 *	Read the data in.
	 */
	unsigned int n;
	fin >> n;
	
	unsigned long long d[n + 1];
	for(unsigned int i = 0; i <= n; i++)
	{
		fin >> d[i];
	}
	
	fin.close();
	
	/**
	 *	Write out the result.
	 */
	MatrixChainMultiplication mcm(d, n);
	fout << mcm.computeIterative();
	fout.close();
	
	return 0;
}