动态编程:盒子堆叠变化

时间:2016-05-29 11:32:21

标签: algorithm dynamic-programming

我们有n个盒子,其尺寸为x,y,z(宽度,高度,深度)。 我们希望将最大数量的盒子插入另一个盒子中。
如果内盒(i)的尺寸严格小于外盒(j)的尺寸,则可以将盒子放在另一个盒子内:x [i]< x [j],y [i]< y [j],z [i]< Z [J]。
CAN' T框可以旋转,可以按任何顺序考虑。

如何通过动态编程实现目标? 问题类似于增长最长的子序列问题? 按升序/降序排列方框是否有意义?

2 个答案:

答案 0 :(得分:2)

对框进行拓扑排序,按如下方式将它们排列成图:每个框是图中的节点,从节点A到节点B的每个有向弧表示相应的框A保持框B.增加此结构一个无限大小的盒子和一个零大小的盒子。

作为拓扑排序,此图将是有向无环图。因此,找到最长路径 NP-hard,而是可以用O(V + E)求解。两个扩充框之间的最长路径包含问题的答案。

设置排序为O(V ^ 2),从排序图中找到解是O(V + E),在此上下文中是O(V ^ 2),这是您的整体求解时间。

答案 1 :(得分:0)

这是C ++中一种简单的自上而下的方法:

#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>

using std::cin;
using std::cout;
using std::vector;
using std::ostream;

// G[i][j]==true if box i will fit inside box j.
// L[i] is the number of boxes that will fit inside box i, or -1 if
//      this value has not been determined.

// Calculate how many boxes will fit inside box j.
static int count(const vector<vector<bool>> &G,vector<int> &L,int j)
{
    int n = L.size();
    int max_x = 0;

    for (int i=0; i!=n; ++i) {
        if (G[i][j]) {
            if (L[i]==-1) {
                L[i] = count(G,L,i);
            }
            int x = L[i]+1;
            if (x>max_x) {
                max_x = x;
            }
        }
    }

    return max_x;
}


int main()
{
    int n; cin >> n;
    vector<int> x(n+1), y(n+1), z(n+1);

    for (int i=0; i!=n; ++i) {
        cin >> x[i] >> y[i] >> z[i];
    }

    // Add a huge box that contains any box
    x[n] = INT_MAX;
    y[n] = INT_MAX;
    z[n] = INT_MAX;

    vector<vector<bool> > G(n+1,vector<bool>(n+1,false));

    for (int i=0; i!=n+1; ++i) {
        for (int j=0; j!=n+1; ++j) {
            G[i][j] = x[i]<x[j] && y[i]<y[j] && z[i]<z[j];
        }
    }

    vector<int> L(n,-1);

    // Print the number of boxes that will fit in the huge box.
    cout << count(G,L,n) << "\n";
}

有很多种方法可以让它更快,但是这显示了允许使用动态编程的递归公式。