package com.ltcode.ds;
/**
* @author LT
* @github [https://github.com/ltcodes] [https://gitee.com/fltcode]
* @date 2021/4/21 - 15:33
* @description 基于动态规划算法的0-1背包问题设计过程与实现
*/
public class Backpack {
// 定义物品种类
static int n = 5;
// 存储每件物品的重量w[i],下标从1开始
static int[] w = {0, 2, 2, 6, 5, 4};
// 存储每件物品的价值v[i]
static int[] v = {0, 6, 3, 5, 4, 6};
// 定义背包容量
static int c = 8;
// 存储m(i, j)相对应的值
static int[][] m = new int[10][10];
// 存储装入或不装入
static int[] x = new int[n + 1];
public static void knapsack(){
// 计算背包的剩余容量上限,范围[0 ~ w[n]-1]
int jMax = min(w[n]-1, c);
// 当0<=j<=w[n]时,m(n,j)=0
for (int j = 0; j <= jMax; j++) {
m[n][j] = 0;
}
// 当j>=w[n]时,m(n,j)=v[n]
for (int j = w[n]; j <= c; j++) {
m[n][j] = v[n];
}
// 从n-1往前开始判断第n个物品到第i个物品能不能装下
for (int i = n-1; i > 1; i--) {
jMax = 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] = max(m[i+1][j], m[i+1][j-w[i]]+v[i]);
}
}
// 判断第n个到第1个物品能不能装下
m[1][c] = m[2][c];
if (c >= w[1]) {
m[1][c] = max(m[1][c], m[2][c-w[1]]+v[1]);
}
}
// 回溯查找最优序列,能装下的赋值为1,不能装下的赋值为0
public static void traceBack(){
for (int i = 1; i < n; i++) {
if (m[i][c] == m[i+1][c]){
x[i] = 0;
} else {
x[i] = 1;
c -= w[i];
}
}
x[n] = m[n][c] != 0 ? 1:0;
}
public static int min(int a, int b){
return a < b ? a:b;
}
public static int max(int a, int b){
return a > b ? a:b;
}
public static void main(String[] args) {
System.out.print("待装物品重量分别为:");
for (int i = 1; i <= n; i++) {
System.out.print(i < n ? w[i] + ", " : w[i]);
}
System.out.println();
System.out.print("待装物品价值分别为:");
for (int i = 1; i <= n; i++) {
System.out.print(i < n ? v[i] + ", " : v[i]);
}
System.out.println();
knapsack();
System.out.println("背包能装的最大价值为:" + m[1][c]);
traceBack();
System.out.print("最优装载序列为:");
for (int i = 1; i <= n; i++) {
System.out.print(i < n ? x[i] + ", " : x[i]);
}
System.out.println();
System.out.print("背包装下的物品编号为:");
for (int i = 1; i <= n; i++) {
if (x[i] == 1) {
System.out.print(i < n ? i + ", " : i);
}
}
/**
* 结果如下:
* 待装物品重量分别为:2, 2, 6, 5, 4
* 待装物品价值分别为:6, 3, 5, 4, 6
* 背包能装的最大价值为:15
* 最优装载序列为:1, 1, 0, 0, 1
* 背包装下的物品编号为:1, 2, 5
*/
}
}
0-1背包问题(动态规划、Java)
最新推荐文章于 2022-04-25 22:51:45 发布