用于求解某种最优性质的问题,动态规划与分治法类似。
例题:
0-1 背包问题:有n种物品和一背包,物品i的重量是wi,其价值为vi,其中wi 和 vi均为正整数,背包的容量为w,现需要考虑如何 选择装入背包的物品,使得装入背包中物品的总价值最大?分析一下:


目标函数:从i个物品 累计求和 i个物品 = n 的总价值
约束条件:当 i个物品的重量 <=背包的容量,x 取值 0【不放入】,1 【放入】

分析下这三种情况:
第一种情况:如果 i=0 表示没有放入物体,w=0,表示重量为0 所以为 0
第二种情况: 当 当前物品的重量大于背包总重量 ,当前物体不放入背包
第三种情况,当 当前物品的 重量小于背包总重量,且 判断,如果当前物品放入背包,求当前物品放入背包后的 总价值 或 当前物品不放入背包,求背包可能容纳的总价值,MAX二者取一。
|
i 物品 \ W 重量 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
|
1 |
0 |
0 |
0 |
4 |
4 |
4 |
4 |
4 |
4 |
4 |
4 |
4 |
4 |
4 |
4 |
4 |
4 |
4 |
|
2 |
0 |
0 |
0 |
4 |
5 |
5 |
5 |
9 |
9 |
9 |
9 |
9 |
9 |
9 |
9 |
9 |
9 |
9 |
|
3 |
0 |
0 |
0 |
4 |
5 |
5 |
5 |
10 |
10 |
10 |
14 |
14 |
14 |
14 |
19 |
19 |
19 |
19 |
|
4 |
0 |
0 |
0 |
4 |
5 |
5 |
5 |
10 |
11 |
11 |
14 |
15 |
16 |
16 |
19 |
21 |
21 |
21 |
|
5 |
0 |
0 |
0 |
4 |
5 |
5 |
5 |
10 |
13 |
13 |
14 |
15 |
17 |
18 |
19 |
21 |
23 |
24 |
分析表格:
当重量 w 越来越大时,我们可以判断 物品 i 是否能放入 每一次变化的 递增+1 中,一共递增 17次,因为我们可容纳的重量是17
java 求出最优解:
/**
* @Author wuxiaotian
* @Date 2021/8/26 11:00
* @Version C1.4
*/
public class Test03 {
void OutPutKnapsackDp(int n,int W, int[] weights,int[] values,int[][] c){
int[] x = new int[5]; //n 表示所有的 物品总数
int i = 0;
for ( i = n; i > 0; i--) {
if(W - 1 >= 0) {
if (c[i][W - 1] == c[i - 1][W - 1]) { //重量为w 的最优选择的背包中不包含该物品 判断当前这个物品 放入和不放入价值相等得话 就不放入
x[i - 1] = 0; //不放入该物品
} else {
x[i - 1] = 1; //放入该物品
System.out.println("总总量:" + W + "当前物品重量:" + weights[i] + "剩余重量:" + (W - weights[i]));
W = W - weights[i]; //更新背包目前的最大容量 总容量 - 当前物品容量
}
}
}
if(c[1][W] == 0){ //第一个物品不放入背包
x[0] = 0;
}else{
x[0] = 1; //第一个物品放入背包
}
for (int j = 0; j <n; j++) {
if(x[j] == 1){
System.out.println(String.format("重量为%d: 价值为%d:",weights[j+1],values[j+1]));
}
}
}
public static void main(String[] args) {
Test03 test03 = new Test03();
int n = 4; //物品个数
int W = 17; //总容量
int[] weights = new int[] {3,4,7,8,9};
int[] values = new int[] {4,5,10,11,13};
int [][] c =new int[5][17];
c[0] = new int[] {0 ,0 ,4, 4 ,4 ,4, 4 ,4 ,4 ,4 ,4 ,4 ,4 ,4 ,4 ,4, 4};
c[1] = new int[] {0 ,0 ,4, 5, 5, 5, 9, 9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9};
c[2] = new int[] {0, 0, 4, 5, 5, 5, 10, 10, 10, 14, 14, 14, 14, 19, 19, 19, 19};
c[3] = new int[] {0, 0, 4, 5, 5, 5, 10, 11, 11, 14, 15, 16, 16, 19, 21, 21, 21};
c[4] = new int[] {0, 0, 4, 5, 5, 5, 10, 13, 13, 14, 15, 17, 18, 19, 21, 23, 24};
for (int i = 0; i <5; i++) {
for (int j = 0; j < weights.length; j++) {
c[i][j] = j;
}
}
test03.OutPutKnapsackDp(n,W,weights,values,c);
}
}
由于时间原因,以上算法可能不够精简,仅仅实现了功能,小伙伴们有更好的算法可以私聊我,一起学习丫
这篇博客介绍了如何使用动态规划解决经典的0-1背包问题,通过一个实例展示了如何在Java中实现找到装入背包中物品的总价值最大化的算法。博主分享了一个可能不够精简的解决方案,并邀请读者分享更优的算法。
5万+





