算法-经典趣题-窃贼问题

一、问题

窃贼问题是一个典型的最优解的问题。窃贼问题的大意如下:

有一个窃贼带着一个背包去偷东西,房屋中共有5件物品,其重量和价值如下。

物品1:6公斤,48元。

物品2:5公斤,40元。

物品3:2公斤,12元。

物品4:1公斤,8元。

物品5:1公斤,7元。

窃贼希望能够拿最大价值的东西,而窃贼的背包最多可装重量为8公斤的物品。那么窃贼应该装下列哪些物品才能达到要求呢?

二、分析

我们来分析一下窃贼问题,窃贼问题是关于最优解的问题,可使用动态规划的思想来解最优化问题。窃贼问题求解的操作过程如下:

(1)首先创建一个空集合。

(2)然后向空集合中增加元素,每增加一个元素就先求出该阶段最优解。

(3)继续添加元素,直到所有元素都添加到集合中,最后得到的就是最优解。

采用上述思路,窃贼问题的求解算法

 

 

 

(1)首先,窃贼将物品i试着添加到方案中。

(2)然后判断是否超重,若未超重,则继续添加下一个物品,重复第一步。

(3)若超重,则将该物品排除在方案之外,并判断未排除的物品价值是否大于已有最大值,如果大于就继续执行;如果不满足,则不必再尝试后续物品了。

三、编程

package com.joshua317;

import java.util.Arrays;
import java.util.Scanner;
import java.util.logging.SocketHandler;

public class Main {
    static double maxPrice;//最大的价值
    static double totalPrice;//物品的总价值
    static double maxWeight;//最大限制的重量
    static  int goodsNum;//可选物品的数量
    static char[] selectTemp;//临时数组

    public static void main(String[] args) {

        System.out.println("窃贼问题-最优化问题");
        System.out.println("请输入窃贼可以装入物品的最大重量");
        Scanner scanner = new Scanner(System.in);
        maxWeight = scanner.nextDouble();
        System.out.println("请输入窃贼可选物品的数量");
        goodsNum = scanner.nextInt();

        Goods[] goods = new Goods[goodsNum];
        totalPrice = 0;

        for (int i = 0; i < goodsNum; i++) {
            Goods temp = new Goods();
            System.out.println("请输入第"+(i+1)+"件物品的重量和价格");
            temp.weight = scanner.nextDouble();
            temp.price = scanner.nextDouble();
            totalPrice += temp.price;
            goods[i] = temp;
        }

        //打印初始化信息
        System.out.println("背包可以装入物品的最大重量为" + maxWeight);
        for (int i = 0; i < goodsNum; i++) {
            System.out.println("第" + (i+1) + "号物品的重量为:"+goods[i].weight + "  价格为:" + goods[i].price);
        }

        //初始化被选择信息
        selectTemp = new char[goodsNum];
        for (int i = 0; i < goodsNum; i++) {
            selectTemp[i] = 0;
        }
        maxPrice = 0;
        //求解
        backPack(goods, 0, 0.0, totalPrice);

        double totalWeight = 0;//总重量
        //打印最佳方案
        System.out.println("可以装入以下物品,使得获取的价值最大");
        for (int i = 0; i < goodsNum; i++) {
            if (goods[i].isSelect == 1) {
                System.out.println("第" + (i+1) + "号物品,其中:重量为:"+goods[i].weight + "  价格为:" + goods[i].price);
                totalWeight += goods[i].weight;
            }
        }
        System.out.println("总重量为:" + totalWeight + "总价值为:" + maxPrice);
    }

    public static void backPack(Goods[] goods, int i, double weight, double tp) {
        int k;
        //将物品i包含在当前方案中,判断重量是否小于等于最大限制的重量
        if (weight + goods[i].weight <= maxWeight) {
            selectTemp[i] = 1;//选择第i个物品
            if (i < goodsNum - 1) {//如果物品i不是最后一个物品
                backPack(goods, i+1, weight + goods[i].weight, tp);
            } else {
                for (k = 0; k < goodsNum; k++) {
                    goods[k].isSelect = selectTemp[k];
                }
                maxPrice = tp;//保存方案的最大价值
            }
        }

        selectTemp[i] = 0;//取消物品i的选择状态
        //判断是否超重,还可以继续添加物品
        if (tp - goods[i].price > maxPrice) {
            if (i < goodsNum - 1) {//如果物品i不是最后一个物品
                backPack(goods, i+1, weight,tp - goods[i].price);
            } else {
                for (k = 0; k < goodsNum; k++) {
                    goods[k].isSelect = selectTemp[k];
                }
                maxPrice = tp - goods[i].price;//保存方案的最大价值
            }
        }
    }


}

class Goods {
    double price;//价钱
    double weight;//重量
    char isSelect;//是否选中到方案里面
}

 

 

 

 

 

 

 

 
posted @ 2021-09-08 19:27  joshua317  阅读(240)  评论(0编辑  收藏  举报