您的位置:首页 > 其它

动态规划-3.9 0-1背包问题

2017-11-08 21:58 288 查看
问题描述:给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问应如何选择装入背包的物品,使得装入背包中物品的总价值最大?

0-1背包问题是一个特殊的整数规划问题。

0-1背包问题的目标函数约束条件如下:



其最优值为m(i,j),即m(i,j)背包容量为j,可选择物品为i,i+1,…,n时0-1背包问题的最优值。由0-1背包问题的最优子结构性质,可以建立计算m(i,j)的递归式如下。



例如:有编号分别为1,2,3,4,5的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和?



代码如下:

public class test3_9 {
public static void knapsack(int[] v,int[] w,int c,int[][] m){
int n = v.length-1;
//若w
>c表示第n个物品重量大于当前剩余容量c,则选择不装(jMax=c,则第一个for循环m
[0]~m
[c]=0)
int jMax = Math.min(w
-1, c);
//1.求m
[j]
for(int j=0;j<=jMax;j++)
m
[j] = 0;
for(int j=w
;j<=c;j++)
m
[j] = v
;
//2.求m[i][j]
for(int i=n-1;i>0;i--){  //从倒数第二个物品向前迭代,共迭代n-2次
jMax = Math.min(w[i]-1, c);
for(int j=0;j<=jMax;j++)
m[i][j] = m[i+1][j];
for(int j=w[i];j<=c;j++)
m[i][j] = Math.max(m[i+1][j], m[i+1][j-w[i]]+v[i]);
}
//3.求m[0][c]
m[0][c] = (w[0]>c)? m[1][c]: Math.max(m[1][c], m[1][c-w[0]]+v[0]);
}
public static void traceback(int[][] m,int[] w,int c,boolean[] x){
int n = w.length-1;
for(int i=0;i<n;i++)
if(m[i][c]==m[i+1][c]) //若相等则说明,第i个物品没有放到背包里
x[i] = false;
else{
x[i] = true;
c -= w[i];
}
x
= (m
[c]>0)? true:false;  //最后一个物品有价值说明最后一个物品放进了背包
}
public static void main(String[] args) {
int[] w = {2,2,6,5,4};
int[] v = {6,3,5,4,6};
int n = v.length;  //物品的数量
boolean[] x = new boolean
;
int c = 10;
int[][] m = new int
[c+1];  //m[][0]~m[][c]
knapsack(v,w,c,m);
traceback(m,w,c,x);
for(int i=0;i<v.length;i++){
for(int j=0;j<=c;j++)
System.out.print(m[i][j]+" ");
System.out.println();
}
for(int i=0;i<n;i++)
System.out.println("第"+(i+1)+"个物品是否放入背包:"+x[i]+" ");
}
}


输出结果:

第1个物品是否放入背包:true
第2个物品是否放入背包:true
第3个物品是否放入背包:false
第4个物品是否放入背包:false
第5个物品是否放入背包:true


总结:0-1背包问题程序求解三大步骤如下

①求m
[j]


②求m[i][j]

③求m[0][c]

时间复杂度为:O(n*c)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: