【问题标题】:Stack of Boxes - Dynamic Programming一堆盒子 - 动态规划
【发布时间】:2016-12-26 20:24:51
【问题描述】:

我目前正在练习一些动态编程。我遇到了一堆盒子。
方框表示为:

struct Box{
    double h;
    double w;
    double d;
};

问题在于创建最高的盒子堆栈,其中堆栈中的每个盒子(在宽度和深度上)都比它上面的盒子大。假设在这种情况下盒子不能旋转。

我将这些盒子存放在std::vector<Box> 中。我首先按宽度然后按深度进行稳定排序,这样每当我选择一个盒子时,我只需要向前搜索下一个适合的盒子。

这是我的问题 - 这是最优的吗?
我想每次我选择一个盒子时,我都需要搜索线性时间 (O(n)) 才能选择下一个可能的盒子。
是否有不同的方法来存储时间复杂度可能更好的盒子?

当然也欢迎任何其他优化。


我的完整代码:

//Get index of next box that fits or -1 if none
int getP(std::vector<Box>& boxes, int n){
    double n_w = boxes[n].w;
    double n_d = boxes[n].d;
    for (int i=n-1; i >= 0; i--){
        if (n_w > boxes[i].w && n_d > boxes[i].d)
            return i;
    }
    return -1;
}

//Get highest possible stack.
double stackOfBoxes(std::vector<Box>& boxes, int n, Box* bottom){
    if (n == -1)
        return 0;
    if (bottom == NULL || (bottom->d > boxes[n].d && bottom->w > boxes[n].w))
        return max(stackOfBoxes(boxes, n-1, bottom),stackOfBoxes(boxes, getP(boxes,n), &boxes[n])+boxes[n].h);
    else
        return stackOfBoxes(boxes, n-1, bottom);
}


int main(){
    std::vector<Box> boxes = { {3,1,1},{5,2,2},{10,7,7} };
    std::stable_sort(boxes.begin(), boxes.end(), sortByW);
    std::stable_sort(boxes.begin(), boxes.end(), sortByD);

    cout << stackOfBoxes(boxes, 2, NULL) << endl;
}

【问题讨论】:

  • this link 怎么样?
  • 在我知道的盒子堆叠问题中,盒子可以旋转(任何一面都可以作为底座)。你是这样的吗?
  • @Nelxost 这是一个有趣的案例,但现在假设它们不能旋转。也编辑过帖子。

标签: c++ algorithm dynamic-programming


【解决方案1】:

代码实际上是不正确的,因为您假设子问题的最佳解决方案可以扩展到包含当前(第 n 个)框,而实际上它不一定。

示例:{2, 50, 1}, {1, 1, 2}, {1, 3, 3}

(上面的例子没有被 2 次排序所改变。)你的算法的 getP(boxes, 3) 将正确地确定第二个框 {1, 1, 2} 是可以在最后一个 {1, 3, 3} 框之前的最新框,但是由请求子问题stackOfBoxes(boxes, 1) 的解决方案,调用代码假设列表中第二个框之前的任何框(即第一个框或第二个框)也可以合法在最后的{1, 3, 3} 框之前——但这不是真的。 stackOfBoxes(boxes, 1) 最终正确返回 2,这只能通过使用第一个框来实现——但外部 stackOfBoxes(boxes, 2) 调用认为它可以在此之上添加最终的 {1, 3, 3} 框,尽管事实上 50 > 3 .

非常清楚stackOfBoxes(boxes, n) 的返回值是什么意思是有帮助的。从您在此处编写代码的方式来看,它必须表示“仅使用索引

(感谢 Nelxost 在我之前的错误描述中发现了一个错误!)

【讨论】:

  • 首先,感谢您的更正和解释。在将其添加到堆栈之前,我总是必须跟踪底部框以便将其与当前的n 框进行比较。我已经用这个案例更正了我的代码,希望现在它涵盖了所有案例。其次,我的问题主要是寻找是否有任何其他(更好的)方法来保存和搜索下一个适合的框。
  • 我无法抽出时间和精力来尝试证明存在错误,但是如果有错误,您可能可以通过生成低于一定大小的所有可能实例来找到它(例如,最多4 个框,所有四个维度都在 1 .. 3) 范围内,并将您的算法结果与每个框的已知良好蛮力算法进行比较。如果你这样做,并写一个英文句子,准确定义你认为stackOfBoxes(boxes, n, bottom) 返回的nbottom(就像我在回答中所做的那样),我会继续关注这个。
  • 还有一件事:你实际上并没有在你的(原始的或更新的)代码中做任何记忆——正如实现的那样,它只是“普通”递归,它需要 n 的指数时间。跨度>
【解决方案2】:

这是我的问题 - 这是最优的吗?

不正确。

我用相同的输入尝试了你的代码,除了我制作的第三个框的深度0.5

Here is the result。它给出了 15,而答案应该是 10,因为没有其他盒子可以放在第三个盒子之上。

【讨论】:

  • 谢谢,我已经更正了我的代码,请参阅下面我对@j_random_hacker 的评论
猜你喜欢
  • 2021-08-05
  • 2017-06-23
  • 2017-05-12
  • 1970-01-01
  • 2012-06-28
  • 1970-01-01
  • 2016-07-01
  • 1970-01-01
相关资源
最近更新 更多