// 部分背包问题
// 在限定条件下,如何从众多物品中选出收益最高的几件物品,这样的问题就称为背包问题。
// 举个简单的例子,商店的货架上摆放着不同重量和价值的商品,一个小偷在商店行窃,
// 他携带的背包只能装固定重量的商品,选择哪些商品才能获得最大的收益呢?这个问题就属于背包问题,
// 限定条件是背包的承重,最终目标是令背包中存放的物品的总收益最高。
// 根据不同的限定条件,背包问题还可以有更细致的划分:
// 0-1背包问题:每件物品都不可再分,要么整个装入背包,要么放弃,不允许出现类似“将物品的 1/3 装入背包”的情况;
// 部分背包问题:每件物品是可再分的,即允许将某件物品的一部分(例如 1/3)放入背包;
// 完全背包问题:挑选物品时,每件物品可以选择多个,也就是说不限物品的数量。
// 多重背包问题:每件物品的数量是有严格规定的,比如物品 A 有 2 件,物品 B 有 3 件。
// 不同的背包问题,对应的解决方案也不相同。本节我们给大家讲解,如何用贪心算法解决部分背包问题。
// 假设商店中有 3 种商品,它们各自的重量和收益是:
// 商品 1:重量 10 斤,收益 60 元;
// 商品 2:重量 20 斤,收益 100 元;
// 商品 3:重量 30 斤,收益 120 元。
//
// 对于每件商品,顾客可以购买商品的一部分(可再分)。一个小偷想到商店行窃,他的背包最多只能装 50 斤的商品,
// 如何选择才能获得最大的收益呢?
// 贪心算法解决此问题的思路是:计算每个商品的收益率(收益/重量),优先选择收益率最大的商品,直至所选商品的总重量达到 50 斤。
package main
import (
"math"
"fmt"
)
// 根据收益率,对记录的商品进行从大到小排序
func sort(w [] float64, p []float64) {
// 用v[]存商品的收益率
v := make([]float64, len(w))
for i := 0; i < len(w); i++ {
v[i] = p[i] / w[i]
fmt.Printf("商品%f收益率是:%f\n", p[i], v[i])
}
fmt.Printf("排序前的收益率是:%f\n", v)
fmt.Printf("排序前的商品总重量是:%f\n", w)
fmt.Printf("排序前的商品总价值是:%f\n", p)
// 根据v数组记录的各个商品收益率的大小,同时对w和p数组进行排序
// 方便后面根据收益率获取到各个商品的信息
for i := 0; i < len(w); i++ {
for j := i + 1; j < len(w); j++ {
if v[i] < v[j] {
v[i], v[j] = v[j], v[i]
w[i], w[j] = w[j], w[i]
p[i], p[j] = p[j], p[i]
}
}
}
fmt.Printf("排序后的收益率是v[i]:%f\n", v)
fmt.Printf("排序后的商品总重量是w[i]:%f\n", w)
fmt.Printf("排序后的商品总价值是p[i]:%f\n", p)
}
// 贪心算法解决部分背包问题
// w记录各个商品的总重量,p记录各个商品的总价值,result记录各个商品装入背包的比例
// W背包的重量
func fractionalKnaspack(w []float64, p []float64, result []float64, W float64) {
// 定义temp为每次能装入背包的重量
var temp float64 = 0
sort(w, p)
for i := 0; ; {
fmt.Printf("各个商品总重量:%f,背包剩余的总重量:%f\n", w[i], W)
// 获取当前还能装入背包的重量
temp = math.Min(w[i], W)
fmt.Printf("装入背包重量:%f\n", temp)
// 获取装入背包的商品的比例
result[i] = temp / w[i]
fmt.Printf("商品装入比例:%f\n", result[i])
// 背包剩余的总重量
W -= temp
i++
fmt.Printf("背包剩余总重量:%f\n", W)
if W <= 0 {
break
}
}
fmt.Printf("最终装入背包的收益率result[i]是:%f\n", result)
}
func main() {
var values float64 = 0
w := []float64{10, 30, 20}
p := []float64{60, 100, 120}
result := make([]float64, len(w))
fractionalKnaspack(w, p, result, 50)
for i := 0; i < len(w); i++ {
if result[i] == 1 {
fmt.Printf("总重量为%f,总价值为%f的商品全部转入\n", w[i], p[i])
values += p[i]
} else if result[i] == 0 {
fmt.Printf("总重量为%f,总价值为%f的商品不装\n", w[i], p[i])
} else {
fmt.Printf("总重量为%f,总价值为%f的商品转入率%f\n", w[i], p[i], result[i]*100)
values += p[i] * result[i]
}
}
fmt.Printf("最终收获的商品价值为%f", values)
}
【算法】贪心算法解决部分背包问题
最新推荐文章于 2024-05-22 21:55:29 发布