Aperçu
La réponse de Jeff Shattock est correcte: c'est équivalent (ou isomorphe, comme l'écrivent les mathématiciens) à un problème d'optimisation combinatoire, mais c'est équivalent au problème d'emballage bin à 1 dimension , pas au problème du sac à dos .
Heureusement pour vous, j'ai du code à partager qui résoudra ce problème pour vous ou toute autre personne ayant accès à un ordinateur Windows avec au moins la version 3.5 du .NET Framework installé.
Une solution approximative
Tout d'abord, téléchargez et installez LINQPad .
Deuxièmement, téléchargez la requête LINQPad que je viens d'écrire - voici le linq (ha) dans le fichier brut. Enregistrez-le en tant que fichier .linq et ouvrez-le dans LINQPad.
Modifiez les paramètres:
Voici la partie du code de requête LINQPad que vous devez modifier:
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";
Changez binSizeMb
la taille de votre «bac», par exemple CD, DVD, ex. int binSizeMb = 650;
pour un CD.
Remarque - la binSizeMb
valeur est interprétée comme ce qu'on appelle parfois un mégaoctet . Contrairement à mon enfance, lorsque tous les multiples d'octets étaient «binaires», parfois «MB» fait maintenant référence à un «mégaoctet décimal» ou exactement 1 000 000 octets, par opposition aux 1 048 576 octets d'un méga-octet (MiB), qui est utilisé dans mon code . Si vous souhaitez changer cela, changez la ligne const int bytesPerMb = 1048576;
du code en const int bytesPerMb = 1000000;
.
Passez rootFileFolderPath
au chemin complet du dossier contenant les fichiers que vous souhaitez «empaqueter dans des bacs», ex. string rootFileFolderPath = @"C:\MySecretBinFilesFolder";
.
Exécutez la requête en appuyant F5sur ou en cliquant sur le bouton Exécuter en haut à gauche de l'onglet de requête.
Résultats
Le code de requête énumérera tous les fichiers du rootFileFolderPath
dossier, récursivement, ce qui signifie qu'il inclura également des fichiers dans tous les sous-dossiers.
Ensuite, il créera des «bacs» pour les fichiers de telle sorte que la taille totale de tous les fichiers de chaque bac soit inférieure ou égale à la taille de bac spécifiée.
Dans le volet de résultats LINQPad, vous verrez deux listes.
La première liste contient tous les fichiers trouvés, classés par ordre décroissant de taille.
La deuxième liste est constituée des bacs créés en «emballant les fichiers», avec une liste des fichiers et leurs tailles, ainsi que la taille restante du bac.
Voici une capture d'écran montrant la deuxième liste et les deux premiers bacs créés:
Analyse du cursus
Selon Wikipedia, l'algorithme que j'ai utilisé - la stratégie First Fit Decreasing (FFD) - ne devrait pas être trop mauvais; Wikipédia déclare:
En 2007, il a été prouvé que le 11/9 OPT + 6/9 lié pour FFD est serré.
«OPT» fait référence à la stratégie optimale (comme quelque chose de potentiellement inaccessible, pas de stratégie réelle particulière).
Sur la base de mes souvenirs quelque peu flous des termes mathématiques impliqués, cela devrait signifier que la stratégie FFD devrait, au pire, emballer les éléments dans environ 1,22 fois le nombre de bacs qu'une stratégie optimale ferait. Ainsi, cette stratégie peut regrouper les éléments dans 5 cases au lieu de 4. Je soupçonne que ses performances sont susceptibles d'être très proches de l'optimalité, sauf pour des tailles spécifiques d'éléments «pathologiques».
Le même article Wikipédia déclare également qu'il existe un "algorithme exact" . Je peux aussi décider de mettre cela en œuvre. Je devrai d'abord lire l'article qui décrit l'algorithme.