问题描述:
0-1背包问题就是给定背包容量、所有物品的重量和价值,问如何将物品装入背包,使得背包中的物品价值是最大的,每个物品只能整个整个的取,不能只取物品的一部分。
下面给出回溯法解决0-1背包问题的Java代码:
import java.util.Scanner;
public class Backtrack {
private static int[] optimalArray; //最优数组
private static int[] currentArray; //当前数组
private static int[] weightArray; //重量数组
private static int[] valueArray; //价值数组
private static int maxValue; //背包最大价值
public static void main(String[] args) {
//获取需要的数据
Scanner scanner = new Scanner(System.in);
System.out.print("请输入背包容量:");
int capacity = scanner.nextInt();
System.out.print("请输入物品数量:");
int number = scanner.nextInt();
System.out.print("请输入物品重量数组:");
String[] weight = scanner.next().split(",");
System.out.print("请输入物品价值数组:");
String[] value = scanner.next().split(",");
//创建相关数组
weightArray = new int[number];
valueArray = new int[number];
currentArray = new int[number];
optimalArray = new int[number];
//给重量数组和价值数组赋值
for (int i = 0; i < number; i++) {
weightArray[i] = Integer.parseInt(weight[i]);
valueArray[i] = Integer.parseInt(value[i]);
}
//计算出所有物品的总价值和总重量
int surplusValue = 0;
int residualWeight = 0;
for (int i = 0; i < number; i++) {
surplusValue+=valueArray[i];
residualWeight+=weightArray[i];
}
//调用方法
knapsack(0,capacity,0,surplusValue,residualWeight);
//输出结果
System.out.println("背包最大价值:" + maxValue);
System.out.print("选取的物品(1代表选中,0代表未选中):");
for (int i = 0; i < optimalArray.length; i++) {
System.out.print(optimalArray[i] + " ");
}
}
/**
* @param layer 当前层数
* @param residualCapacity 背包剩余容量
* @param currentValue 当前背包价值
* @param surplusValue 子树剩余价值
* @param residualWeight 子树剩余重量
*/
public static void knapsack(int layer, int residualCapacity, int currentValue, int surplusValue, int residualWeight) {
//判断当前背包价值是否大于背包的最大价值,如果大于且当前背包剩余容量大于0,则将背包的最大价值替换成当前背包价值,并替换最优数组
if (residualCapacity >= 0 && currentValue > maxValue) {
maxValue = currentValue;
for (int i = 0; i < layer; i++) {
optimalArray[i] = currentArray[i];
}
for (int i = layer; i < optimalArray.length; i++) {
optimalArray[i] = 0;
}
}
//剪枝条件判断,如果子树剩余重量小于等于背包剩余容量则不再进行后续的探索
if (residualWeight <= residualCapacity) {
//如果子树剩余价值加背包当前背包价值大于最大价值,则替换最大价值并更新最优数组
if (surplusValue + currentValue > maxValue) {
maxValue = surplusValue+currentValue;
for (int i = 0; i < layer; i++) {
optimalArray[i] = currentArray[i];
}
for (int i = layer; i < optimalArray.length; i++) {
optimalArray[i] = 1;
}
}
}else{
if(residualCapacity>0){
//选择当前层物品,递归调用
currentArray[layer] = 1;
knapsack(layer+1,residualCapacity-weightArray[layer],
currentValue+valueArray[layer],surplusValue-valueArray[layer],
residualWeight-weightArray[layer]);
//不选择当前层物品,递归调用
currentArray[layer] = 0;
knapsack(layer+1,residualCapacity,currentValue,surplusValue-valueArray[layer],
residualWeight-weightArray[layer]);
}
}
}
}