private void matrixChainOrder(int p[])
	{
		for (int i = 1; i <= n; i++)
			m[i][i] = 0;
		
		/*
		 * The bottom up calculation needs to proceed only in the upper 
		 * triangle and that too diagonal-wise as
		 * 	1. i < j and m[i][j] for i > j does not makes sense
		 *  2. The diagonal represents the solution of the smallest
		 *     sub-problems. The elements above it(diagonal wise) represent the
		 *     next bigger subproblems which make use of the solutions below 
		 *     them and so on. Proceeding diagonal wise solves all smaller 
		 *     subproblems first which are needed by the larger subproblems later.
		 */
		for (int d = 2; d <=n; d++) // for each diagonal
		{
			 // step through the elements of the diagonal
			for(int i = 1, j = d; j <=n ; j++, i++)
			{
				m[i][j] = Integer.MAX_VALUE;
				// the number of scalar multiplications is the minimum of all
				// types of parenthesizations
				for(int k = i; k < j; k++)
				{
					int min = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
					if ( min < m[i][j]) {
						m[i][j] = min;
						split[i][j] = k;
					}
					
				}
			}
		}
	}