定义
在限定条件下,如何从众多物品中选出收益最高的几件物品,这样的问题就称为背包问题。
举个简单的例子,帕朵菲莉丝偷进货的时候有一个可以装 15kg 的背包,一共有 5 个物品重量为一个数组 [1, 2, 1, 12, 4]
,每个物品的价值也为一个数组 [5, 8, 5, 50, 15]
,可以购买商品的一部分(可再分),如何使每次进货收益最高?
啊啊啊啊啊啊啊!帕朵菲莉丝!猫猫!米哈游你坏事做尽!
思路
贪心算法解决此问题的思路是:计算每个商品的收益率(收益/重量),优先选择收益率最大的商品,直至所选商品的总重量达到 15kg。
选择收益最大的商品可以将收益放在一个数组当中,将数组进行排序,同时将对应的物品重量数组、物品价值数组排序,并每次拿到最大的数组。
贪心算法,贪心贪心,就贪心在每次都要拿最好最厉害的。根据这个思想很容易理解上面的文字
图示
我们假定一个数组(该数组只是便于理解而假定出来的),用来存放物品的重量weight
、物品的价值price
以及物品的利益profit
根据刚刚的贪心算法思想,贪心一点每次都拿最大最好的,那么我们怎么获取最大最好的呢?答案是先对这个假定的数组根据物品利益profit
进行排序。最终得到的数组顺序:
此时依次将利益最大的物品放入背包:
最后一个元素比较特殊,背包无法将全部物品装入,只能装入一部分,而题目是可以让我们对物品进行分割的,所以可以取20重量的物品放进背包,而价值也应该相应减少到对应价值,具体见图示
背包容量为0,说明装不下了,再贪心也装不了,那就结束,返回结果result为最终收益。
具体代码:
import { Component, Vue } from "vue-property-decorator";
@Component({
components: {},
})
export default class PartPack extends Vue {
// 包的容量
pack = 0;
// 物品重量
weight = [];
// 物品价值
price = [];
// 物品对应收益的数组
profit = [];
// 最终结果
result = 0;
// 根据收益进行排序
sort(weight, price) {
let length = weight.length;
let temp = 0;
// 获取收益数组
for (let i = 0; i < length; i++) {
this.profit[i] = weight[i] / price[i];
}
// 冒泡排序,将weight[]、price[]、profit[]三个数组进行排序
for (let i = 0; i < length; i++) {
for (let j = 1; j < length - i; j++) {
if (this.profit[j] < this.profit[j - 1]) {
// 这三段代码就是刚刚说的假定的数组
temp = this.profit[j - 1];
this.profit[j - 1] = this.profit[j];
this.profit[j] = temp;
temp = weight[j - 1];
weight[j - 1] = weight[j];
weight[j] = temp;
temp = price[j - 1];
price[j - 1] = price[j];
price[j] = temp;
}
}
}
}
partPack(weight, price, pack) {
let result = 0;
let i = 0;
// 排序
this.sort(weight, price);
while (pack > 0) {
// 如果能装下这个物品,就装入整个物品,如果装不下了, 就装背包剩下能装的
let temp = pack > weight[i] ? weight[i] : pack;
// 计算今天收入
result += (temp / weight[i]) * price[i];
// 背包被占了多少
pack -= temp;
// 后台打印每个物品赚多少
console.log(
"这次第" +
(i + 1) +
"个物品装进了" +
((temp / weight[i]) * 100).toFixed(2) +
"%,赚了" +
(temp / weight[i]) * price[i] +
"个银币!"
);
i++;
}
return result;
}
display() {
this.pack = 50;
this.weight = [10, 20, 30];
this.price = [60, 140, 120];
this.result = this.partPack(this.weight, this.price, this.pack);
console.log("罐头!咱这次进货一共赚了" + this.result + "个银币!");
}
mounted() {
this.display();
}
}