我们有n个盒子,其尺寸为x,y,z(宽度,高度,深度)。
我们希望将最大数量的盒子插入另一个盒子中。
如果内盒(i)的尺寸严格小于外盒(j)的尺寸,则可以将盒子放在另一个盒子内:x [i]< x [j],y [i]< y [j],z [i]< Z [J]。
CAN' T框可以旋转,可以按任何顺序考虑。
如何通过动态编程实现目标? 问题类似于增长最长的子序列问题? 按升序/降序排列方框是否有意义?
答案 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";
}
有很多种方法可以让它更快,但是这显示了允许使用动态编程的递归公式。