visão global
A resposta de Jeff Shattock está correta: isso é equivalente (ou isomórfico, como matemáticos escrevem) a um problema de otimização combinatória, mas é equivalente ao problema de empacotamento de lixeira unidimensional , não ao problema da mochila .
Para sua sorte, tenho um código para compartilhar que resolverá esse problema para você ou qualquer outra pessoa, com acesso a um computador Windows com pelo menos a versão 3.5 do .NET Framework instalada.
Uma solução difícil
Primeiro, baixe e instale o LINQPad .
Segundo, baixe a consulta LINQPad que acabei de escrever - aqui está o linq (ha) no arquivo bruto. Salve-o como um arquivo .linq e abra-o no LINQPad.
Mude os parâmetros:
Aqui está a parte do código da consulta LINQPad que você deve alterar:
int binSizeMb = 4476; // This is the (floor of the) total size of a DVD+R reported by CDBurnerXP.
string rootFileFolderPath = @"F:\2006 - Polyester Pimpstrap Intergalactic Extravaganza multicam";
Mude binSizeMb
para o tamanho da sua 'lixeira', por exemplo, CD, DVD, ex. int binSizeMb = 650;
para um CD.
Nota - o binSizeMb
valor é interpretado como às vezes chamado de mebibyte . Ao contrário da minha infância, quando todos os múltiplos de bytes eram 'binários', às vezes 'MB' agora se refere a um 'megabyte decimal' ou exatamente 1.000.000 de bytes, em oposição aos 1.048.576 bytes de um mebibyte (MiB), usado no meu código . Se você deseja alterar isso, altere a linha const int bytesPerMb = 1048576;
no código para const int bytesPerMb = 1000000;
.
Mude rootFileFolderPath
para o caminho completo da pasta que contém os arquivos que você deseja 'empacotar em compartimentos', ex. string rootFileFolderPath = @"C:\MySecretBinFilesFolder";
.
Execute a consulta pressionando F5ou clicando no botão Executar na parte superior esquerda da guia de consulta.
Resultados
O código da consulta enumerará todos os arquivos da rootFileFolderPath
pasta, recursivamente, o que significa que também incluirá arquivos em todas as subpastas.
Em seguida, ele criará 'compartimentos' para os arquivos, de modo que o tamanho total de todos os arquivos em cada compartimento seja menor ou igual ao tamanho especificado.
No painel de resultados do LINQPad, você verá duas listas.
A primeira lista é de todos os arquivos encontrados, listados em ordem decrescente de tamanho.
A segunda lista são os compartimentos criados por 'empacotar os arquivos', com uma lista dos arquivos e seus tamanhos, bem como o tamanho restante do compartimento.
Aqui está uma captura de tela mostrando a segunda lista e os dois primeiros compartimentos criados:
Análise Curricular
De acordo com a Wikipedia, o algoritmo que eu usei - a estratégia First Fit Decreasing (FFD) - não deve ser tão ruim; A Wikipedia afirma:
Em 2007, foi comprovado que o limite de 11/9 OPT + 6/9 para FFD é apertado.
'OPT' refere-se à estratégia ideal (como algo potencialmente inacessível, e não uma estratégia real em particular).
Com base nas minhas memórias um tanto confusas dos termos matemáticos envolvidos, isso deve significar que a estratégia do FFD deve, na pior das hipóteses, empacotar itens em ~ 1,22 vezes o número de caixas que uma estratégia ideal faria. Portanto, essa estratégia pode empacotar itens em 5 compartimentos em vez de 4. Suspeito que seu desempenho provavelmente esteja muito próximo do ideal, exceto por tamanhos específicos de itens 'patológicos'.
O mesmo artigo da Wikipedia também afirma que existe um "algoritmo exato" . Eu também posso decidir implementar isso. Vou ter que ler o artigo que descreve o algoritmo primeiro.