Visión de conjunto
La respuesta de Jeff Shattock es correcta: esto es equivalente (o isomorfo, como escriben los matemáticos) a un problema de optimización combinatoria, pero es equivalente al problema de empaquetamiento del contenedor unidimensional , no el problema de la mochila .
Por suerte para ti, tengo un código para compartir que resolverá este problema para ti, o para cualquier otra persona, con acceso a una computadora Windows con al menos la versión 3.5 de .NET Framework instalada.
Una solución aproximada
Primero, descargue e instale LINQPad .
En segundo lugar, descargue la consulta LINQPad que acabo de escribir : aquí está el linq (ha) en el archivo sin formato. Guárdelo como un archivo .linq y ábralo en LINQPad.
Cambiar los parámetros:
Aquí está la parte en el código de consulta LINQPad que debe cambiar:
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";
Cambie binSizeMb
al tamaño de su 'contenedor', por ejemplo, CD, DVD, ej. int binSizeMb = 650;
para un CD
Nota : el binSizeMb
valor se interpreta como lo que a veces se denomina mebibyte . Al contrario de mi infancia, cuando todos los múltiplos de bytes eran 'binarios', a veces 'MB' ahora se refiere a un 'megabyte decimal' o exactamente 1,000,000 bytes, en oposición a los 1,048,576 bytes de un mebibyte (MiB), que se usa en mi código . Si desea cambiar esto, cambie la línea const int bytesPerMb = 1048576;
en el código a const int bytesPerMb = 1000000;
.
Cambie rootFileFolderPath
a la ruta completa de la carpeta que contiene los archivos que desea 'empacar en contenedores', ej. string rootFileFolderPath = @"C:\MySecretBinFilesFolder";
.
Ejecute la consulta F5presionando o haciendo clic en el botón Ejecutar en la parte superior izquierda de la pestaña de consulta.
Resultados
El código de consulta enumerará todos los archivos de la rootFileFolderPath
carpeta, de forma recursiva, lo que significa que también incluirá archivos en todas las subcarpetas.
Luego, creará 'contenedores' para los archivos de modo que el tamaño total de todos los archivos en cada contenedor sea menor o igual que el tamaño especificado.
En el panel de resultados de LINQPad verá dos listas.
La primera lista es de todos los archivos que encontró, enumerados en orden decreciente por tamaño.
La segunda lista son los contenedores creados al 'empaquetar los archivos', con una lista de los archivos y sus tamaños, así como el tamaño restante del contenedor.
Aquí hay una captura de pantalla que muestra la segunda lista y los dos primeros contenedores creados:
Análisis de cursores
Según Wikipedia, el algoritmo que utilicé, la estrategia de primer ajuste decreciente (FFD), no debería ser tan malo; Wikipedia dice:
En 2007, se comprobó que el límite 11/9 OPT + 6/9 para FFD es ajustado.
'OPT' se refiere a la estrategia óptima (como algo potencialmente inalcanzable, no una estrategia real en particular).
Basado en mis recuerdos algo borrosos de los términos matemáticos involucrados, esto debería significar que la estrategia FFD debería, en el peor de los casos, empacar elementos en ~ 1.22 veces el número de contenedores que una estrategia óptima. Por lo tanto, esta estrategia podría agrupar elementos en 5 contenedores en lugar de 4. Sospecho que es probable que su rendimiento sea muy cercano al óptimo, excepto para tamaños de elementos 'patológicos' específicos.
El mismo artículo de Wikipedia también establece que existe un "algoritmo exacto" . Puedo decidir implementar eso también. Tendré que leer primero el documento que describe el algoritmo.