14天阅读挑战赛
努力是为了不平庸~
算法学习有些时候是枯燥的,这一次,让我们先人一步,趣学算法!欢迎记录下你的那些努力时刻(算法学习知识点/算法题解/遇到的算法bug/等等),在分享的同时加深对于算法的理解,同时吸收他人的奇思妙想,一起见证技术er的成长~
当搜索到某一步时,如果原先的选择不是最优选择或者达不到目标,就回退一步重新选择,如果再不通就再退回重新选择的方法叫做回溯法。满足回溯条件的某个状态叫做回溯点。
解题步骤:
隐约束:对能否得到问题的可行解或最优解而做出的约束,如果不符合隐约束,说明当前分支不存在问题的解就没有必要搜索
隐约束分为约束函数和限界函数。对能否得到问题的可行解的约束称为约束函数。对能否得到问题的最优解的约束称为限界函数。
题目背景:把重量为w,价值为v的物品,逐个放进一个总容量为W的背包中,在不超过背包容量的情况下,使背包内的物品价值最大,求能够放进哪些东西?
假设物品的重量和价值信息如下
let weight = [10,20,3,7,9,15]
let value = [23,30,10,14,15,25]
根据之前的解题步骤,解题流程如下:
let weight = [10, 20, 3, 7, 9, 15];
let value = [23, 30, 10, 14, 15, 25];
// 对应索引的物品是否装入,1表示装入,0表示不装入
let x = [0, 0, 0, 0, 0, 0];
// 当前最优解集合
let bestx = [];
// 当前最优值
let bestv = 0;
// 当前放入背包的物品的总价值
let cv = 0;
// 当前放入背包的物品的总重量
let cw = 0;
// 背包的总容量
let W = 40;
// 节点的层次
let n = 6;
// 计算价值上界
function bound(i) {
let rp = 0;
while (i < n) {
rp += value[i];
i++;
}
return rp;
}
//回溯法,t为层次
function backtrack(t) {
//到达叶子
if (t >= n) {
for (let j = 0; j < n; j++) {
//记录最优解
bestx[j] = x[j];
}
//记录最优值
bestv = cv;
return;
}
//如果满足约束条件,则搜索左子树
if (cw + weight[t] <= W) {
x[t] = 1;
cw += weight[t];
cv += value[t];
backtrack(t + 1);
//还原现场
cw -= weight[t];
cv -= value[t];
}
//如果满足限界条件,则搜索右子树
if (bound(t + 1) > bestv) {
x[t] = 0;
backtrack(t + 1);
}
}
backtrack(0);
console.log(bestx);