我需要编写一个应用程序来获取文件列表(一些大文件,一些小文件)并尽可能高效地将它们放到DVD(或CD或其他任何文件)上。这个应用程序的重点是在移动到第二张光盘之前使用尽可能多的第一张光盘,尽可能多地填充第二张光盘,然后再移动到第三张光盘上等。
(注意:应用程序不必对DVD进行实际刻录,只需要找出最合适的效果)。
我最初认为我有一个很好的游戏计划,通过生成文件的排列,然后检查每个组合,看看哪个最合适。 (我的求助请求可以HERE)
但是文件越多,所需的时间就越长......指数级。所以我想就如何最好地实现这一点提出一些意见。
有什么想法吗?并且,一如既往,C#代码总是受到赞赏。
答案 0 :(得分:12)
您所面对的是knapsack problem。链接的维基百科页面包含更多信息,包括建议的解决方法。
答案 1 :(得分:9)
简单算法:
答案 2 :(得分:2)
对于仍然对这个问题感兴趣的人... 我写了一个实用工具,我用它来将文件装入一组磁盘/光盘。 它使用基于命令行/文件的界面。 版本有C,C ++和& Java(不是C#)。
http://whizman.com/code/diskfit.tgz
更详细的信息在diskfit.tgz:Doc / diskfit.txt文件中。
(AGPL3)
我们可能将这个问题描述为0-1多背包, 或线性箱包装。 (感谢jon-skeet关于背包问题的链接。)
Dthorpe解决了线性垃圾箱包装问题,以确保足够的垃圾箱/磁盘适合 所有文件[很好地O(n)或O(n lg n)快速 - 在没有电子表格的情况下也是可行的 必须写一个脚本]。
基本上,diskfit(上面链接的实用程序)输出合格的文件集 基于0-1单背包, 并且用户选择一个磁盘文件集来组装到磁盘集中 - 协助用户(但不是完全自动化)同时:
完整的这种磁盘集的完全程序化选择, 将是一个额外的功能。 应用0-1单背包解决方案是不够的, 自动光盘[贪婪]。 (考虑3个容量为6的背包,以及具有相同价值的可用物品 和权重:{1,1,2,2,3,4,5}。 将0-1背包单独应用到第一个背包上会选择 {1,1,2,2}获得总和值4 - 之后我们无法适应所有的 剩下的第二个&第三背包 - 而我们知道我们可以适应3个背包中的所有物品 {1,2,3}& {1,5}& {2,4}。)
答案 3 :(得分:1)
for each file
is there enough room this dvd?
yes, store it here
no, is there room on another already allocated dvd?
yes, store it there
no, allocate another dvd and store it there
答案 4 :(得分:1)
虽然这对于某些应用程序的程序来说是一个很酷的问题...但是在您的应用程序中,为什么不使用WinRAR或其他一些能够将存档拆分为特定大小的文件块的归档程序。您可以将每个块的大小设置为DVD大小,然后烧掉。
编辑:您遇到的一个问题是,如果您的某个文件大于媒体的大小,则无法刻录该文件。
答案 5 :(得分:0)
如果你开始把尽可能多的最大文件放到一张DVD上,然后用尽可能多的最小文件填充它(从最小的文件开始)。
对每个磁盘的剩余文件重复此过程。
我不确定这会给你提供完美的报道/分发,但我认为它可能会在某种程度上解决你的需求。
答案 6 :(得分:0)
使用回溯来获取要刻录到dvd 1的最佳文件集,然后将它们从列表中排除并使用其余文件的回溯来获得dvd 2的最佳填充等等
答案 7 :(得分:0)
我发现了许多应该解决这个问题的工具,但是他们都试图最小化所用光盘的TOTAL数量,而我只对最适合SINGLE光盘的SINGLE文件子集感兴趣。
所以我结束了自己编写的名为“ss”的工具(来自“子集和”算法)。 该工具仍然有问题,无法递归目录,但它对我有用。 :)
答案 8 :(得分:0)
这个问题是Bin Packing Problem并且是NP完成的,这意味着如果你想要一个真正的最佳解决方案,你将需要指数时间。然而,有些方法提供的解决方案不是最优,但运行速度要快得多。
假设我们有一个无限的磁盘列表。将每个文件按大小降序排列,然后将每个文件添加到它适合的第一个磁盘中。这称为首先适合减少,在最坏的情况下需要11/9 OPT + 6/9磁盘。如果您以随机顺序选择文件,则需要11/9 OPT + 1个磁盘。
有些算法会将事情收紧,请参阅上面的维基百科链接了解更多详情。