0/1背包问题:
由于前段时间研究了动态规划,今天就利用动态规划来分析及解决0/1背包问题!
问题描述:一个旅行者有一个最多能用M公斤的背包,现在有N件物品,
它们的重量分别是W1,W2,...,Wn,
它们的价值分别为v1,v2,...,vn.
若每种物品只有一件求旅行者能获得最大总价值?
问题分析:问题求的是最大的价值,我们定义f[i,j]表示前i种物体放进容量为j的背包里面获取到最大的价值,定义f[I,j]是子问题,显然,子问题具有重叠性,具有最优解性质,所以,此问题可以利用动态规划来解决,分析得到子问题最优解f[I,j]具有以下性质:
f[i,j]= 0,{i=0 OR j=0}-----------------------------临界值
f[i,j]= f[i-1,j],{j<wi}----------------------------递归公式1
f[i,j]= max(f[i-1,j],f[i,j-wi]+vi),{j>wi}----------递归公式2
则n*m的f表格来记录各个过程的值(利用空间来换取时间)
下面我举例来说明,如果w={3,6,5} v={4,3,6} n=3,m=15
表格如图所示:
F[i][j] |
J=0 |
J=1 |
J=2 |
J=3 |
J=4 |
J=5 |
J=6 |
V7 |
V8 |
J=9 |
I=0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
I=1 |
0 |
0 |
0 |
4 |
4 |
4 |
4 |
4 |
4 |
4 |
I=2 |
0 |
0 |
0 |
4 |
4 |
4 |
4 |
4 |
4 |
7 |
I=3 |
0 |
0 |
0 |
4 |
4 |
6 |
6 |
6 |
10 |
10 |
如是我们利用java语言来描述o-1背包问题
public class BeiBao { public int beiBaoFun(int n, int m, int[] w, int[] v) {//n个物体,容量为m的背包,wi表示第i个的重量,v表示第i个中价值。 /* f[i,j]表示取i件商品填充一个容积为j的背包的最大价值,显然问题的解就是f[n,m]*//* * 显然:f[i,j]=f[i-1,j] {j<Vi} 或者 max{f[i-1,j],f[i,j-Vi]+Pi} {j>=Wi} 或者 0 {i=0 OR j=0} */ int[][] f = new int[n + 1][m + 1]; for (int j = 0; j <= m; j++) { f[0][j] = 0;/* 初始化:当i=0时,f[0][j]=0 */ } for (int i = 0; i <= n; i++) { f[i][0] = 0;/* 初始化:当j=0时,f[i][0]=0 */ } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { if (w[i] <= j) { /* 如果当前物品的容量小于背包容量 */ f[i][j] = max(v[i] + f[i - 1][j - w[i]], f[i - 1][j]); } else { f[i][j] = f[i - 1][j]; } } } return f[n][m]; } private int max(int i, int j) { return i > j ? i : j; } public static void main(String[] args) { BeiBao bb = new BeiBao(); int[] w = { 0, 3, 6, 5 };/* 注意:由于算法的设计问题,把第0项也要设计上去但是我在计算时候只不把他考虑进去 */ int[] v = { 0, 4, 3, 6 }; int res = bb.beiBaoFun(w.length - 1, 15, w, v); System.out.println(res); } } 过程分析: 0 0 4 4 4 4 4 4 4 4 4 4 4 4 4 0 0 4 4 4 4 4 4 7 7 7 7 7 7 7 0 0 4 4 6 6 6 10 10 10 10 10 10 13 13
欢迎大家交流~~~