本文为joshua317原创文章,转载请注明:转载自joshua317博客 算法-经典趣题-窃贼问题 - joshua317的博客
一、问题
窃贼问题是一个典型的最优解的问题。窃贼问题的大意如下:
有一个窃贼带着一个背包去偷东西,房屋中共有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;//是否选中到方案里面
}
Java
Copy
本文为joshua317原创文章,转载请注明:转载自joshua317博客 算法-经典趣题-窃贼问题 - joshua317的博客