0-1背包问题
给一个固定大小,能够携重W的背包以及一组有价值重量的物品,找出一个最佳的方案,使得装入包中的物品重量不超过W且总价值最大。
例:物品个数n=5,物品重量weights=[2,2,6,5,4],物品价值values=[6,3,5,4,6],背包总容量W=10。
f(0,2)=6;f(1,2) =6; f(2,4)=9; f(2,8)=6+5=11; f(2,10)=6+3+5=14; f(3,5) = 9; f(3,7) = 10 ; f(3,9) = 13 ; f(3,10) = 6+5+3; f(4,4) = 9; f(4,6) = 12; f(4,8) = 15; f(4,9)= 9<15 ;f(4,10) = 15
f(i,j)表示所放物品的最大价值
f(0,2)=6
第二行j=2时通过比较价值来选择放物品0还是物品1;
放物品0的话f(0,j)=6;放物品1要计算背包放入1之后还有多少容量,再根据其容量查出价值,再加上物品1 的价值;可表示为
f(0,j-w(1))+v(1) ;与f(0,j)的价值进行比较,取最大值;
公式:f(i-1,j-w(i))+v(i)
如此循环,类推。。。
代码如下:
function knapsack(weights, values, w){
var n = weights.length;//获取物品个数
var f=[[]];//定义f的矩阵
//处理第一行
for(var j=0;j<=w;j++){
if(j<weights[0]){//如果此时容不下不下物品0的重量,价值为0
f[0][j]=0;
}else{
f[0][j]=values[0];//否则容量为物品0的价值
}
}
for(var j=0;j<=w;j++){
for(var i=1;i<=(n-1);i++){
if(!f[i]){//如果是新的物品,创建新的一行
f[i]=[];
}
if(j<weights[i]){//如果第i个物品的重量超过此时能承受的重量,那么其最优值等于上一行的最优值
f[i][j]=f[i-1][j];
}else{
f[i][j]=Math.max(f[i-1][j],f[i-1][j-weights[i]]+values[i]);//此行和上一行的价值比较同一个重量下,不同物品价值比较;
}
}
}
return f[n-1][w];
}
var res = knapsack([2,2,6,5,4],[6,3,5,4,6],10)
console.log(res)