3

我有一个数组,其中包含不同尺寸材料的列表:{4,3,4,1,7,8}。但是,该箱可以容纳最大 10 号的材料。我需要找出包装数组中所有元素所需的最小箱数。

对于上面的数组,你可以打包成 3 个 bin 并按如下方式划分它们:{4,4,1}, {3,7}, {8}. 还有其他可能的安排也适合三个备用管道,但不能用更少的

我试图通过递归来解决这个问题,以便更好地理解它。

我正在使用这个DP 公式(pdf 文件的第 20 页)

考虑具有 n = ∑nj 个项的输入 (n1;:::;nk)
确定可以打包到单个 bin 中的 k 元组(输入的子集)的集合
即所有元组 (q1;:::; qk) 其中 OPT(q1;:::;qk) = 1
用 Q 表示这个集合 对于每个 k 元组 q ,我们有 OPT(q) = 1
使用递归计算剩余值: OPT(i1;:: :;ik) = 1 + minOPT(i1 - q1;:::;ik - qk)

我已经编写了代码,它适用于小型数据集。但是如果将我的数组的大小增加到超过 6 个元素,它会变得非常慢 -大约需要 25 秒来解决包含 8 个元素的数组你能告诉我算法是否有问题吗?我不需要替代解决方案 ---只需要知道为什么这么慢,以及如何改进它

这是我用 C++ 编写的代码:

void recCutStock(Vector<int> & requests,  int numStocks)
{
 if (requests.size() == 0)
 {

     if(numStocks <= minSize)
    {
        minSize = numStocks;

    }
//   cout<<"GOT A RESULT : "<<numStocks<<endl;
        return ;
 }
 else
 {
    if(numStocks+1 < minSize) //minSize is a global variable initialized with a big val
    {
     Vector<int> temp ; Vector<Vector<int> > posBins;
     getBins(requests, temp, 0 , posBins); // 2-d array(stored in posBins) containing all possible single bin formations

    for(int i =0; i < posBins.size(); i++)
    {
        Vector<int> subResult;
        reqMinusPos(requests, subResult,  posBins[i]);  // subtracts the initial request array from the subArray
        //displayArr(subResult);


            recCutStock(subResult,  numStocks+1);


    }
    }
    else return;
 }

}

getBins 函数如下:

void getBins(Vector<int> & requests, Vector<int> current, int index, Vector<Vector<int> > & bins)

{

if (index == requests.size())

{

if(sum(current,requests) <= stockLength && sum(current, requests)>0 )

        {
                bins.add(current);
            //  printBins(current,requests);
            }
            return ;
        }
        else
        {

        getBins(requests, current, index+1 , bins);
                current.add(index);
            getBins(requests, current, index+1 , bins);
        }
}
4

5 回答 5

6

动态规划算法为 O(n^{2k}),其中 k 是不同项目的数量,n 是项目的总数。无论实施如何,这都可能非常缓慢。通常,在解决 NP 难题时,需要使用启发式算法来提高速度。

我建议您考虑 Coffman 等人的 Next Fit Decreshing Height (NFDH) 和 First Fit Decreasing Height (FFDH)。它们分别是 2 最优和 17/10 最优,并且它们在 O(n log n) 时间内运行。

我建议您首先尝试 NFDH:按降序排序,将结果存储在链表中,然后重复尝试从头开始插入项目(最大值在前),直到您填满 bin 或没有更多项目可以被插入。然后转到下一个 bin 以此类推。

参考资料

Owen Kaser,Daniel Lemire,标签云绘图:云可视化算法,社交信息组织的标签和元数据(WWW 2007),2007。(有关相关讨论,请参见第 5.1 节。)

EG Coffman, Jr.、MR Garey、DS Johnson 和 RE Tarjan。面向水平的二维打包算法的性能界限。SIAM J. 计算机,9(4):808–826,1980。

于 2011-11-29T15:30:51.247 回答
1

但是如果将我的数组的大小增加到超过 6 个元素,它会变得非常慢 - 需要大约 25 秒来解决包含 8 个元素的数组你能告诉我算法是否有问题吗?

用蛮力是正常的。蛮力根本无法扩展。

于 2011-11-30T16:24:03.290 回答
1

在您的情况下:箱大小 = 30,项目总数 = 27,至少需要 3 个箱。您可以尝试先拟合递减,并且它有效!

更多改进方法:使用 3 个垃圾箱和 27 个尺寸单位,您将剩下 3 个单位的空间。这意味着您可以忽略大小为 1 的项目;如果你把其他的放进 3 个箱子里,它会放在某个地方。剩下 26 个尺寸单位。这意味着您将在一个垃圾箱中至少有两个单元是空的。如果你有大小为 2 的物品,你也可以忽略它们,因为它们适合。如果您有两个大小为 2 的项目,您也可以忽略大小为 3 的项目。

您有两个大小为 7 + 3 的项目,这正是 bin 大小。总有一个最佳解决方案,这两个在同一个 bin 中:如果“7”与其他项目一起,它们的大小将是 3 或更小,因此如果它在另一个 bin 中,您可以将它们与“3”交换。

另一种方法:如果你有 k 个项目 >= bin size / 2(此时你不能有两个项目等于 bin size / 2),那么你需要 k 个 bins。这可能会增加您最初估计的最小 bin 数量,从而增加所有 bin 中的保证空白空间,从而增加一个 bin 中剩余空间的最小大小。如果对于 j = 1, 2, ..., k 您可以将所有项目与它们一起放入可能适合同一个 bin 的 j 个 bin 中,那么这是最佳的。例如,如果您有 8、1、1 码但没有 2 码,则箱中的 8+1+1 将是最佳选择。由于您还剩下 8 + 4 + 4,并且没有任何东西适合 8,因此仅在其 bin 中的“8”是最佳的。(如果您有尺寸为 8、8、8、2、1、1、1 的物品,而没有其他尺寸为 2 的物品,则将它们装入三个箱子中是最佳选择)。

如果您有大件物品,可以尝试更多的东西:如果您有一件大件物品,并且适合它的最大物品与任何适合的物品组合一样大或更大,那么将它们组合起来是最佳选择。如果有更多空间,则可以重复此操作。

所以总而言之,稍微思考一下就将问题简化为将两个尺寸为 4、4 的物品放入一个或多个箱子中。对于更大的问题,每一点都有帮助。

于 2014-04-03T18:21:16.273 回答
0

我已经编写了一个装箱解决方案,我可以推荐最适合随机顺序的方案。

于 2011-11-30T16:31:34.207 回答
0

在尽你所能减少问题之后,如果可能的话,你将面临将 n 个项目放入 k 个箱子中的问题,否则放入 k + 1 个箱子中,或者放入 k + 2 个箱子中等等。如果 k 个箱子失败,那么你知道在 k + 1 个箱的最佳解决方案中,您将有更多的空白空间,这可能会删除更多的小物品,所以这是首先要做的事情。

然后你尝试一些简单的方法:首先适合降序,然后适合降序。我尝试了第一次适合降序的相当快速的变化:只要两个最大的项目适合,添加最大的项目。否则,找到适合的单个项目或两个项目的最大组合,然后添加单个项目或该组合中的较大者。如果这些算法中的任何一个将您的物品放入 k 个箱子中,那么您就解决了这个问题。

最终你需要蛮力。您可以决定:您是尝试将所有内容放入 k 个 bin 中,还是尝试证明这是不可能的?您将有一些空地可以玩。假设 10 个大小为 100 的箱子和总大小为 936 的物品,这将留下 64 个单位的空白空间。如果您只将尺寸为 80 的物品放入您的第一个垃圾箱,那么您的 64 件商品中有 20 件已经用完,这使得从那里找到解决方案变得更加困难。所以你不要按随机顺序尝试。您首先尝试将第一个垃圾箱完全或接近完全装满的组合。由于小物品更容易完全装满容器,因此您尽量不要在第一个垃圾箱中使用它们,而是将它们留到以后,当您选择较少的物品时。当你找到要放入垃圾箱的物品时,尝试其中一种简单的算法,看看他们是否能完成它。例如,如果 first fit downding 将 90 个单位放入第一个箱中,而您只是设法将 99 个单位放入其中,则很可能这是足以容纳所有内容的改进。

另一方面,如果空间非常小(例如 10 个箱子,总物品大小为 995),您可能想证明无法安装物品。您不需要关心优化算法以快速找到解决方案,因为您需要尝试所有组合才能看到它们不起作用。显然,您需要使用这些数字将至少 95 个单位放入第一个箱中,依此类推;这可能使快速排除解决方案变得容易。如果您证明 k 个 bin 是不可实现的,那么 k+1 个 bin 应该是一个更容易的目标。

于 2014-04-03T18:43:33.400 回答