我有一堆要刻录到DVD的媒体文件,但是由于每张DVD只能容纳4.5GB,因此我必须找到一种组织文件的最佳方式,以使用最少数量的DVD(否则每张DVD中都留有空白空间) DVD可以轻松添加)。有什么工具可以帮助您吗?
许多年前,有一个DOS实用程序可对软盘进行此操作。
我有一堆要刻录到DVD的媒体文件,但是由于每张DVD只能容纳4.5GB,因此我必须找到一种组织文件的最佳方式,以使用最少数量的DVD(否则每张DVD中都留有空白空间) DVD可以轻松添加)。有什么工具可以帮助您吗?
许多年前,有一个DOS实用程序可对软盘进行此操作。
Answers:
杰夫·沙托克(Jeff Shattock)的答案是正确的,因为它等效于(或同构,如数学家所写)组合优化问题,但等效于一维箱装问题,而不是背包问题。
幸运的是,我有一些要共享的代码,它们可以为您或其他任何人解决此问题,并且可以访问至少安装了.NET Framework 3.5版的Windows计算机。
首先,下载并安装LINQPad。
其次,下载我刚刚编写的LINQPad查询 -这是原始文件的linq(ha)。将其另存为.linq文件,然后在LINQPad 中将其打开。
更改参数:
这是您应该更改的LINQPad查询代码中的部分:
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";
更改binSizeMb
为“ bin”的大小,例如CD,DVD。int binSizeMb = 650;
一张CD。
注意 –该binSizeMb
值被解释为有时称为mebibyte的值。与我的童年时期相反,当所有字节的倍数都是“二进制”时,有时“ MB”现在指的是“十进制兆字节”或正好是1,000,000字节,而不是我的代码中使用的兆字节(MiB)的1,048,576字节。如果要更改此设置,const int bytesPerMb = 1048576;
请将代码中的行更改为const int bytesPerMb = 1000000;
。
更改rootFileFolderPath
到包含您希望的文件“包装成箱”,当然该文件夹的完整路径。string rootFileFolderPath = @"C:\MySecretBinFilesFolder";
。
通过F5单击或单击查询选项卡左上方的“ 执行”按钮来运行查询。
查询代码将rootFileFolderPath
递归枚举文件夹中的所有文件,这意味着它还将在所有子文件夹中包含文件。
然后,它将为文件创建“箱”,以使每个箱中所有文件的总大小小于或等于指定的箱大小。
在LINQPad结果窗格中,您将看到两个列表。
第一个列表是找到的所有文件的列表,按大小降序列出。
第二个列表是通过“打包文件”创建的垃圾箱,其中包含文件及其大小以及垃圾箱的剩余大小的列表。
这是显示第二个列表和创建的前两个容器的屏幕截图:
根据Wikipedia的说法,我使用的算法-首次适应递减(FFD)策略-应该还不错。维基百科指出:
2007年,事实证明,FFD的约束11/9 OPT + 6/9很小。
“ OPT”是指最佳策略(因为某些可能无法实现的策略,而不是任何特定的实际策略)。
基于我对所涉及的数学术语的模糊记忆,这应该意味着FFD策略在最坏的情况下应将物料打包成最佳策略所能容纳的箱数的〜1.22倍。因此,这种策略可能会将物品包装到5个装箱中,而不是4个装箱中。我怀疑除了特定的“病理”物品尺寸外,它的性能可能非常接近最佳状态。
维基百科的同一篇文章还指出,存在“精确算法”。我可能也会决定实施。我必须先阅读描述该算法的论文。
您可以在完成本教程的某些部分之后,在Hitchhiker的Haskell指南中采用该程序的变体之一。本教程围绕准确解决您将事物分布到多个磁盘上的问题而编写,从而使解决方案得到逐步完善,本教程第3章的以下段落对此进行了说明:
预赛已经足够了。让我们打包一些CD。
您可能已经意识到,我们的问题是经典的。这被称为“背包问题” (如果您还不知道它是什么,可以用谷歌搜索一下。有超过100000个链接)。
让我们从贪婪的解决方案开始...
这是一个类似的问题(尽管不尽相同:这里没有要求进行优化),在这里您可能会找到针对您的任务的更有用的解决方案/程序(如果将发布它们):
通常,Haskell代码具有很强的表现力(因为Haskell是一种用于高度抽象编程的语言),因此可以轻松掌握。
查看其中一种解决方案的代码时,请记住,我们要编写的程序的顶层结构非常简单,如本教程第1章所述:
现在让我们考虑一下我们的程序将如何运行并以伪代码表示它:
main = Read list of directories and their sizes. Decide how to fit them on CD-Rs. Print solution.
听起来合理吗?我是这么想的。
让我们简化一下生活,现在假设我们将在程序外部的某个地方计算目录大小(例如,使用“
du -sb *
”),并从stdin中读取此信息。
并进一步仔细研究解决方案的各个部分。
多年以前,我编写了PHP脚本来执行此类任务:https : //bitbucket.org/borszczuk/php-backup-maker/
另外,尝试使用Discfit,它会选择要在各种磁盘上复制的文件和目录: