Algorithm 动态规划:盒子堆叠变化

Algorithm 动态规划:盒子堆叠变化,algorithm,dynamic-programming,Algorithm,Dynamic Programming,我们有n个盒子,它们的尺寸是x,y,z(宽度,高度,深度)。 我们希望在另一个盒子中插入最大数量的盒子。 如果内框(i)的大小严格小于外框(j)的大小,则可以将一个框放入另一个框中:x[i]n; 向量x(n+1)、y(n+1)、z(n+1); 对于(int i=0;i!=n;++i){ cin>>x[i]>>y[i]>>z[i]; } //添加一个包含任何框的大框 x[n]=INT_MAX; y[n]=整数最大值; z[n]=INT_MAX; 向量G(n+1,向量(n+1,false)); 对

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

如何使用动态规划实现目标?
该问题类似于最长递增子序列问题?

按升序/降序排列框是有意义的?

在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";
}
#包括
#包括
#包括
#包括
使用std::cin;
使用std::cout;
使用std::vector;
使用std::ostream;
//G[i][j]==如果框i适合于框j,则为真。
//L[i]是可装入框i的框数,如果是,则为-1
//该值尚未确定。
//计算箱子j内可容纳多少个箱子。
静态整数计数(常数向量和G、向量和L、整数j)
{
int n=L.size();
int max_x=0;
对于(int i=0;i!=n;++i){
if(G[i][j]){
如果(L[i]==-1){
L[i]=计数(G,L,i);
}
int x=L[i]+1;
如果(x>最大值x){
max_x=x;
}
}
}
返回max_x;
}
int main()
{
int n;cin>>n;
向量x(n+1)、y(n+1)、z(n+1);
对于(int i=0;i!=n;++i){
cin>>x[i]>>y[i]>>z[i];
}
//添加一个包含任何框的大框
x[n]=INT_MAX;
y[n]=整数最大值;
z[n]=INT_MAX;
向量G(n+1,向量(n+1,false));
对于(int i=0;i!=n+1;+i){
对于(int j=0;j!=n+1;++j){

G[i][j]=x[i]对长方体进行拓扑排序,将它们排列成一个图,如下所示:每个长方体都是图中的一个节点,从节点a到节点B的每个有向弧表示对应的长方体a容纳长方体B。用无限大的长方体和零大小的长方体扩充此结构

作为拓扑排序,此图将是一个有向无环图。因此,查找最长路径不是NP难的,而是可以在O(V+E)中解决的。两个增广框之间的最长路径包含问题的答案


设置排序是O(V^2),从排序图中查找解决方案是O(V+E),在本上下文中是O(V^2)这是您的总体解决方案时间。

到目前为止您想出了什么?基于面积/体积的排序可能会有所帮助如果我们有2D框,我们可以按宽度排序,并在诱导的高度序列中找到最长的增加子序列,n个框需要O(n*log(n))时间。我不确定3D框的时间复杂性是否可能。