Files
Go-http_framework/util/KnapsackOptimization/KnapsackSearchAnswerUtil.go
T

112 lines
3.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* @Author : huangzj
* @Time : 2020/8/5 11:50
* @Description
*/
package KnapsackOptimization
import "fmt"
type KnapsackSearchAnswer struct {
BagCapacity int //背包的总容量上限
BagItemList []*BagItem //背包道具列表
ItemNum int //道具的数量
bestPath []int //最佳路径(怎么存放价值最高)
currentBestPath []int //最佳路径(当前解)
bestValue []int //每个容量最大价值
currentValue int //当前价值
currentWeight int //当前重量
lastBestValue int //目前装载的最优价值
surplusValue int //剩余道具价值
}
func NewKnapsackSearchAnswer(bagItemList []*BagItem, bagCapacity int) *KnapsackSearchAnswer {
if bagCapacity <= 0 {
panic("背包总容量不能小于等于0")
}
answer := &KnapsackSearchAnswer{
BagCapacity: bagCapacity,
BagItemList: bagItemList,
ItemNum: len(bagItemList),
bestPath: make([]int, len(bagItemList)+1),
currentBestPath: make([]int, len(bagItemList)+1),
bestValue: make([]int, len(bagItemList)+1),
}
//初始化剩余道具价值等于所有道具总价值
for _, r := range bagItemList {
answer.surplusValue = answer.surplusValue + r.Value
}
return answer
}
//回溯法计算最佳路径和最大达到价值
func (cmd *KnapsackSearchAnswer) DynamicPlanForBestValue() {
cmd.initParam() //初始化第一个数组为空道具
cmd.BackTrack(1) //从第一个道具开始进行路径搜索
}
func (cmd *KnapsackSearchAnswer) BackTrack(step int) {
//遍历到最后一个道具
if step > cmd.ItemNum {
//如果当前总价值大于上一次装载的最佳价值
if cmd.currentValue > cmd.lastBestValue {
//最终的最佳路径用当前最佳路径来替换
for i := 1; i <= cmd.ItemNum; i++ {
cmd.bestPath[i] = cmd.currentBestPath[i]
}
cmd.lastBestValue = cmd.currentValue
return
}
}
//装入该道具之后,剩余的价值要减去当前道具的价值
cmd.surplusValue = cmd.surplusValue - cmd.BagItemList[step].Value
//当前道具的总重量没有超重
if cmd.currentWeight+cmd.BagItemList[step].Weight <= cmd.BagCapacity {
cmd.currentBestPath[step] = 1 //当前道具选中了,设置为1
cmd.currentValue = cmd.currentValue + cmd.BagItemList[step].Value //计算当前价值
cmd.currentWeight = cmd.currentWeight + cmd.BagItemList[step].Weight //计算当前价值
cmd.BackTrack(step + 1) //继续遍历下一个道具
cmd.currentValue = cmd.currentValue - cmd.BagItemList[step].Value //遍历完成要恢复成原来的价值
cmd.currentWeight = cmd.currentWeight - cmd.BagItemList[step].Weight //遍历完成要恢复成原来的重量
}
//这边是剪枝的操作,如果剩余价值加上当前价值会超过上一次的最佳价值,那么就要往右子树遍历,否则不操作.
if cmd.surplusValue+cmd.currentValue > cmd.lastBestValue {
cmd.currentBestPath[step] = 0 //当前路径置为0,不选择该位置
cmd.BackTrack(step + 1)
}
cmd.surplusValue = cmd.surplusValue + cmd.BagItemList[step].Value
}
//输出最佳路径解
func (cmd *KnapsackSearchAnswer) PrintBestSearchPath() {
for index, r := range cmd.bestPath {
if r == 1 {
fmt.Print(" ")
fmt.Println(fmt.Sprintf("道具的价值是:%d,道具的重量是%d", cmd.BagItemList[index].Value, cmd.BagItemList[index].Weight))
}
}
}
func (cmd *KnapsackSearchAnswer) initParam() {
itemList := make([]*BagItem, 0)
itemList = append(itemList, &BagItem{})
itemList = append(itemList, cmd.BagItemList...)
cmd.BagItemList = itemList
}
func (cmd *KnapsackSearchAnswer) BestValue() int {
return cmd.lastBestValue
}