我遇到一个算法问题。
给出n个盒子,每个盒子具有固定的重量和强度(均以kg给出)。 Box的力量告诉我们它能承受的最大重量是多少。我们必须形成最高堆的给定盒子(每个盒子具有相同的高度)。你应该提出一种算法,它总是给出一个最优解,即k盒的最长序列(k <= n)。
嗯,这是我已经想出的解决方案:
看起来这个算法工作得很好,但我不确定它是否总是给出最优解 - 可能它没有。我一直在想动态解决方案,类似于背包问题的解决方案,但我不确定它是否可以通过这种方式解决。对于我的问题,似乎没有最佳的子结构。
提前感谢您的帮助。 :)
答案 0 :(得分:3)
默认情况下,我会尝试分支,从底部向上构建塔。给定一个部分建造的塔,你可以在完成的塔的高度上设置一个限制。如果部分建造的塔可以承受额外的X重量,你可以计算出在额外重量超过X之前你可以添加多少箱子 - 只是按重量增加的顺序挑出剩余的箱子,忽略它们的强度。如果有重量为零的盒子,请将它们放在预处理阶段,然后将它们推到顶部。不太准确的界限是X除以最轻的未使用的盒子的重量。
考虑到这样的约束,使用回溯搜索来构建你的塔,丢弃所有部分答案,这些答案不可能扩展到比目前为止找到的最佳答案更高的塔。
答案 1 :(得分:0)
这是Javascript中的算法
// Array of boxes [weight,strength]
var AB=[[1,2],[3,4],[7,3],[1,10],[10,1],[4,8], [1,10]];
// for each item make set of items Potentially Above
// can leave this out and just say all others are Potentially Above
var w=0,s=1;// indices for weight, strength
for(var i=0; i<AB.length;i++){
var B = AB[i];
B.pa=[];// array of potentially above boxes
for(var j=0; j<AB.length;j++){
if(i!=j && AB[j][w]<=B[s]){// not the same box and box B can support it
B.pa.push(j);// at to array of potentially above boxes
}
}
}
// Display the weights that each box can support
for(var i=0; i<AB.length;i++){
var B = AB[i];
c("Item"+i+" Weight="+B[w]+", Strength="+B[s]+", Weights= "+B.pa );
}
var stacksMax=[];
var heightMax=0;
var stack = [];// height of boxes in stack
var height=0;
var canCarryWt=1e99;//Infinity;// the ground can carry anything
// Try each box in turn as the lowest box
for(var i=0; i<AB.length;i++){
stack = Array(AB.length);// array of heights
height=0;
testBox(i);
}
// Test a box for the boxes it can support (recursive)
function testBox(i){
if(!stack[i]){// avoid cyclic
var B=AB[i];
if(canCarryWt>=B[w]){// cadd add this box
var couldCarryWt=canCarryWt;
canCarryWt = Math.min(canCarryWt-B[w],B[s]);
stack[i]=++height;
// test sub items
for(var j=0;j<B.pa.length;j++){
testBox(B.pa[j]);
}
// test height for being the highest
if(height>heightMax){
stacksMax = [];// clear all the stacks
heightMax = height;
}
if(height==heightMax){
// add a copy of stack to stacksMax
stacksMax.push(stack.slice());
}
// reset values
height--;
canCarryWt=couldCarryWt;
stack[i]=0;
}
}
}
// Sort and Display
var topFirst=true;
var sortedStack=Array(heightMax)
for(var k=0; k<stacksMax.length; k++){
// Sort items
stack=stacksMax[k];
for(var i=0;i<stack.length;i++){
if(stack[i]){
if(topFirst){// nb heights are 1..
sortedStack[heightMax-stack[i]]=i;
}
else{
sortedStack[stack[i]-1]=i;// -1 for 0array
}
}
}
// Display
drawHorizRule();
var weightSupported=0;
for(i=0;i<heightMax;i++) {
var B= AB[sortedStack[i]];
var status = (B[s]>= weightSupported)?"OK":"ERROR";
c("Height"+i+" Box="+sortedStack[i] + ",["+B[w]+","+B[s] + "] "+status);
weightSupported+=B[w];
}
}
// Display functions
function c(s){
// this depends on your environment
}
function drawHorizRule(){
c("<hr/>");
}
答案 2 :(得分:0)
您可以使用动态编程解决此问题。
weight[i] := weight of box i
strength[i] := strength of box i
N(w,b) := maximum number of boxes you can stack <= weight w with box b on bottom
请注意,要计算N(w,b)
,请将框b
放在底部。然后计算可放在其上的最大盒子数。如果你循环通过可以放在它上面的可能的盒子,这很容易做到。
然后你有了递归关系:
N(w,b) = 1+max{ N( min(w-weight[b],strength[b]),i ) }
您的答案是:max{ N(W,b) }
其中W=sum(weight[i])
。