回溯法解决0-1背包问题(Java实现)

问题描述:

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]);

            }
        }
    }
}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值