Algorithm 包装完整
完整的包装问题Algorithm 包装完整,algorithm,data-structures,Algorithm,Data Structures,完整的包装问题 有一个宽度为W,高度为H的容器,有N个矩形包,目标是我们必须插入m(m它看起来像一个背包“变体”:我们取一个元素,或者不取 递归方法 对于给定的v(每个元素都是一个框),以及当前的总宽度s 我们可以考虑递归函数。 def递归(v,s) 其中包括: 如果v为空或s==0(我们无法填充更多的框)返回{s:0,cost:0} 抽头v的第一个元素为(w,h,cost)(您将cost定义为w*h) 三种可能性: 不考虑当前框 p1 = recurse(v, s) s-w>=0: r
有一个宽度为W,高度为H的容器,有N个矩形包,目标是我们必须插入m(m它看起来像一个
背包
“变体”:我们取一个元素,或者不取
递归方法
对于给定的v
(每个元素都是一个框),以及当前的总宽度s
我们可以考虑递归函数。
def递归(v,s)
其中包括:
- 如果v为空或s==0(我们无法填充更多的框)
返回{s:0,cost:0}
- 抽头
的第一个元素为v
(您将cost定义为w*h)(w,h,cost)
- 三种可能性:
- 不考虑当前框
p1 = recurse(v, s)
- s-w>=0:
r = recurse(v, s-w) p2 = { s: w+r.s, c: cost + r.cost }
- s-h>=0:
r = recurse(v, s-h) p3 = { s: h+r.s, c: cost + r.cost }
- 不考虑当前框
p_i
(根据p_i.s
首先,然后是p_i.cost
)
你可以用递归(v,16)
动态方法
我们可以初始化所有可能的和的结构
最简单的是大小为17的数组(对于sum==0到16)(之后称为层
)
层的每个元素都包含:用于达到该成本的最小成本
,框
initialize the layer according to the boxes
foreach box(w,h,cost) of v
nextLayer = copy(layer)
//layerW is simply the idx of layerEl, aka the sum of width of layerEl.boxes
forall layerEl, layerW of the layer
if layerEl.boxes contain box
//skip that current layerEl
break
if layerEl is valid: (it is not an "empty" box due to initialization)
//we may obtain a new sum: box.w + layerEl.w
//that new sum can be compared to layer[ box.w + layerW ]
//update layer[ box.w + layerW ] only if
//* layer[ box.w + layerW ] is invalid
//* OR its cost is greater
if update:
nextLayer[ box.w + layerW ] = {
cost: box.cost + layerEl.cost,
boxes: box U layerW.boxes
}
//do the same with box.h
layer = nextLayer
//got it: layer[16]
最后,我们使用了v
的所有框(或不使用),我们可以只取第16层el
下面是标准递归(带记忆(cache
);以及dp implem
//https://stackoverflow.com/questions/58369646/complete-packing-of-packets
//==>找到所有给出宽度的和,并取最小的权重
var v=[[2,6]、[6,4]、[4,4]、[6,3]、[1,12]、[7,3]、[3,5]、[1,2];
风险价值成本=[12,24,16,18,12,21,15,10];
var-maxW=16;
var cache={};
功能记录(v、深度、w){
if(depth==-1 | | w==0)返回{w:0,cost:0,v:[]};
设id=深度+'-'+w;
if(cache[id])返回cache[id];
//不要接受电流
设best=rec(v,深度-1,w);
设[a,b]=v[深度];
让成本=成本[深度];
让排序=[a,b].map(el=>{
如果(w-el>=0){
//我们可以带走艾尔
设res=rec(v,深度-1,w-el);
返回{
w:el+res.w,
成本:成本+资源成本,
v:[el].混凝土(res.v)
}
}
}).过滤器(x=>!!x);
if(排序长度){
//最小化w,对于相等的w,选择最小重量
最佳=已排序。concat(最佳)。排序((a,b)=>{
如果(a.wb.w){
返回-1;
}
返回a.成本-b.成本;
})[0];
}
cache[id]=最佳;
回报最好;
}
console.log(rec(v,v.length-1,maxW));
函数dp(){
//把所有的总数加起来
//对于缩进宽度,请选择重量最小的宽度
//第i层中的idx表示宽度==i,
//第i个元素保持最佳的“组合”(最小成本),从而达到该宽度
让layer=newarray(maxW+1).fill(0).map(w=>Object.assign({},{cost:1000}));
v、 forEach((elems,i)=>{
让成本=成本[i];
forEach元素(el=>{
如果(层[el]。成本==1000 | |层[el]。成本>成本){
层[el]={cost:cost,s:new Set([el]),索引:new Set([i])}
}
})
});
对于(变量i=v.length-1;i>=0;--i){
设[a,b]=v[i];
让成本=成本[i];
设next=layer.slice(0);
每层(c,w)=>{
//当前(宽度)和无效,锤击时间
如果(成本=1000)返回;
//您不能使用自己两次(v[i]+初始化)
如果(c.index.has(i)){return}
[a,b].forEach(el=>{
如果(w+el>maxW){
返回;
}
设最佳=层[w+el];
//lhs总和有效,可以覆盖无效总和(层[w+el]。成本==1000)
如果(成本+层[w]。成本<层[w+el]。成本| |层[w+el]。成本==1000){
最佳={成本:成本+层[w]。成本,
新集合([el].concat([…层[w].s]),
索引:新集合([i].concat([…层[w].index]))
}
}
次[w+el]=最佳;
});
});
层=下一层;
}
返回层[maxW];
}
设res=dp();
log({cost:res.cost,v:[…res.s],index:[…res.index]});
r = recurse(v, s-w)
p2 = {
s: w+r.s,
c: cost + r.cost
}
r = recurse(v, s-h)
p3 = {
s: h+r.s,
c: cost + r.cost
}
initialize the layer according to the boxes
foreach box(w,h,cost) of v
nextLayer = copy(layer)
//layerW is simply the idx of layerEl, aka the sum of width of layerEl.boxes
forall layerEl, layerW of the layer
if layerEl.boxes contain box
//skip that current layerEl
break
if layerEl is valid: (it is not an "empty" box due to initialization)
//we may obtain a new sum: box.w + layerEl.w
//that new sum can be compared to layer[ box.w + layerW ]
//update layer[ box.w + layerW ] only if
//* layer[ box.w + layerW ] is invalid
//* OR its cost is greater
if update:
nextLayer[ box.w + layerW ] = {
cost: box.cost + layerEl.cost,
boxes: box U layerW.boxes
}
//do the same with box.h
layer = nextLayer
//got it: layer[16]