Quod erat demonstrandum
@Hudell quase, mas ainda não foi a solução correta. Por exemplo, com { 1, 2, 3, 6, 13 } o seu programa particiona em { 2, 3, 6 } e { 1, 13 }, fica 11/14, que não é ótimo (o melhor seria { 1, 2, 3, 6 } e { 13 }, com 12/13 e uma diferença de apenas 1).
Fiz uma solução recursiva em haskell aqui pra demonstrar como faria com bruteforce:
Dá pra otimizar bem: o sum ali percorre a lista toda, dava pra fazer em tempo constante, mas é só pra passar a ideia mesmo. Pra fazer do jeito mais performático os tipos das funções iam ficar meio conturbados :d
A ideia é, pra cada elemento, decidir se ele vai ou não na primeira lista de forma a maximizar o valor da primeira lista sem estourar o limite de metade da soma (arredondado pra cima ou pra baixo, tanto faz, só muda qual das partições fica maior em caso de não ser possível dividir por igual). Por isso a complexidade é O(2^n), é equivalente a gerar todas as combinações de True e False para cada elemento da lista e fazer um teste (idealmente, em tempo constante, que não é o caso da minha ali, mas enfim...). Como tem 2^n possíveis combinações de 0 e 1 pra n "bits", fica a complexidade exponencial aí.
Fiz uma solução recursiva em haskell aqui pra demonstrar como faria com bruteforce:
Código:
partition :: [Int] -> ([Int], [Int])
partition p = partitionRec p 0
where
s = sum p
upperHalf = s - s `div` 2
partitionRec :: [Int] -> Int -> ([Int], [Int])
partitionRec [] _ = ([], [])
partitionRec (x:xs) s
| x + s > upperHalf = ignore
| sum (fst ignore) > sum (fst pick) = ignore
| otherwise = pick
where
ignore = case partitionRec xs s of
(a, b) -> (a, x:b)
pick = case partitionRec xs (s + x) of
(a, b) -> (x:a, b)
main = putStrLn $ show $ partition [1, 2, 3, 6, 13]
Dá pra otimizar bem: o sum ali percorre a lista toda, dava pra fazer em tempo constante, mas é só pra passar a ideia mesmo. Pra fazer do jeito mais performático os tipos das funções iam ficar meio conturbados :d
A ideia é, pra cada elemento, decidir se ele vai ou não na primeira lista de forma a maximizar o valor da primeira lista sem estourar o limite de metade da soma (arredondado pra cima ou pra baixo, tanto faz, só muda qual das partições fica maior em caso de não ser possível dividir por igual). Por isso a complexidade é O(2^n), é equivalente a gerar todas as combinações de True e False para cada elemento da lista e fazer um teste (idealmente, em tempo constante, que não é o caso da minha ali, mas enfim...). Como tem 2^n possíveis combinações de 0 e 1 pra n "bits", fica a complexidade exponencial aí.
Última edição: