/// <summary>
        /// Gets the solution from computed values.
        /// </summary>
        /// <param name="n">O número a ser decomposto.</param>
        /// <param name="p">The number of components.</param>
        /// <param name="offsets">Os deslocamentos iniciais.</param>
        /// <param name="lastValue">The last computed value.</param>
        /// <param name="table">The table.</param>
        /// <returns>The solution.</returns>
        private IntMinWeightTdecompResult <CostType> GetSolution(
            int n,
            int p,
            int[] offsets,
            VertexCostPair lastValue,
            List <List <VertexCostPair> > table)
        {
            var sum = 0;

            for (int j = 0; j < offsets.Length; ++j)
            {
                sum += offsets[j];
            }

            var temporarySolution = new int[p + 1];
            var i = p;

            temporarySolution[i] = n;
            --i;
            temporarySolution[i] = lastValue.Vertex + i + sum;
            var cost = lastValue.Cost;

            --i;
            for (; i > 0; --i)
            {
                sum                 -= offsets[i];
                lastValue            = table[i][lastValue.Vertex];
                temporarySolution[i] = lastValue.Vertex + i + sum;
            }

            var result = new List <int>();

            for (i = 0; i < p; ++i)
            {
                result.Add(temporarySolution[i + 1] - temporarySolution[i]);
            }

            return(new IntMinWeightTdecompResult <CostType>(result, cost));
        }
        /// <summary>
        /// Constrói o tuplo ordenado que corresponde à t-decomposição de n de acordo com a matriz
        /// de custos especificada.
        /// </summary>
        /// <param name="n">O número a ser decomposto.</param>
        /// <param name="matrix">A matriz dos custos.</param>
        /// <returns>A decomposição caso exista e nulo caso contrário.</returns>
        /// <exception cref="ArgumentNullException">Se a matriz for nula.</exception>
        public IntMinWeightTdecompResult <CostType> Run(
            int n,
            List <List <CostType> > matrix)
        {
            if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }
            else if (n < matrix.Count)
            {
                // Para existir solução, o número a ser decomposto terá de ser superior ao número de elementos
                // na decomposição.
                return(null);
            }
            else
            {
                var countVertices = this.CountVertices(matrix);
                if (countVertices < 0 || countVertices < n)
                {
                    // Não é possível encontrar solução quando n é superior ao número de elementos na matriz
                    // nem quando existe alguma linha vazia.
                    return(null);
                }
                else
                {
                    var p = matrix.Count;
                    var verticesInfoTable = new List <List <VertexCostPair> >();
                    if (0 < p)
                    {
                        var verticesInfoLine  = new List <VertexCostPair>();
                        var offSets           = new int[p - 1];
                        var precomputedNumber = n - p + 1;
                        var currentCosts      = matrix[0];
                        var generalOffset     = n - countVertices - 1;
                        offSets[0] = Math.Max(generalOffset + currentCosts.Count, 0);
                        for (int j = offSets[0]; j < currentCosts.Count && j < precomputedNumber; ++j)
                        {
                            var currentCost = currentCosts[j];
                            verticesInfoLine.Add(new VertexCostPair()
                            {
                                Cost   = currentCosts[j],
                                Vertex = 0
                            });
                        }

                        verticesInfoTable.Add(verticesInfoLine);

                        for (int i = 1; i < p - 1; ++i)
                        {
                            var previousInfoLine = verticesInfoLine;
                            verticesInfoLine   = new List <VertexCostPair>();
                            currentCosts       = matrix[i];;
                            offSets[i]         = Math.Max(generalOffset + currentCosts.Count, 0);
                            precomputedNumber -= offSets[i];

                            var count             = 0;
                            var previousLineValue = previousInfoLine[0];
                            for (int k = offSets[i]; k < currentCosts.Count && count < precomputedNumber; ++k)
                            {
                                verticesInfoLine.Add(new VertexCostPair()
                                {
                                    Cost   = this.ring.Add(previousLineValue.Cost, currentCosts[k]),
                                    Vertex = 0
                                });

                                ++count;
                            }

                            var lastIndex = count - 1 + offSets[i];
                            var lastCost  = currentCosts[lastIndex];
                            for (int j = 1; j < previousInfoLine.Count && count < precomputedNumber; ++j)
                            {
                                verticesInfoLine.Add(new VertexCostPair()
                                {
                                    Cost   = this.ring.Add(lastCost, previousInfoLine[j].Cost),
                                    Vertex = j
                                });

                                ++count;
                            }

                            for (int j = 1; j < previousInfoLine.Count && j < precomputedNumber; ++j)
                            {
                                var maxValue = precomputedNumber - j;
                                for (int k = offSets[i]; k < currentCosts.Count - 1 && k < maxValue; ++k)
                                {
                                    var currentPreviousValue = previousInfoLine[j].Cost;
                                    var tempCost             = this.ring.Add(currentPreviousValue, currentCosts[k]);
                                    var currentVertexLine    = verticesInfoLine[k + j - offSets[i]];
                                    if (this.comparer.Compare(tempCost, currentVertexLine.Cost) < 0)
                                    {
                                        currentVertexLine.Cost   = tempCost;
                                        currentVertexLine.Vertex = j;
                                    }
                                }
                            }

                            verticesInfoTable.Add(verticesInfoLine);
                        }

                        // p iguala o número total de componentes do custo
                        currentCosts = matrix[p - 1];
                        var lastOffSet = Math.Max(generalOffset + currentCosts.Count, 0);
                        precomputedNumber -= lastOffSet;
                        var vertex = verticesInfoLine.Count;
                        var diff   = precomputedNumber - vertex;
                        --vertex;
                        var lastValue = new VertexCostPair()
                        {
                            Cost   = this.ring.Add(verticesInfoLine[vertex].Cost, currentCosts[diff]),
                            Vertex = vertex
                        };

                        --vertex;
                        for (int i = diff + 1; i < currentCosts.Count && vertex >= 0; ++i)
                        {
                            var currentValue = this.ring.Add(verticesInfoLine[vertex].Cost, currentCosts[i]);
                            if (this.comparer.Compare(currentValue, lastValue.Cost) < 0)
                            {
                                lastValue.Cost   = currentValue;
                                lastValue.Vertex = vertex;
                            }

                            --vertex;
                        }

                        return(this.GetSolution(n, p, offSets, lastValue, verticesInfoTable));
                    }
                }
            }

            return(null);
        }