go:Backtracking Algorithm

项目结构:

Go 复制代码
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Backtracking Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/7/23 7:03
# User      :  geovindu
# Product   : GoLand
# Project   : goalgorithms
# File      : bead.go
*/
package dto
 
// BeadItem 多宝手串珠子实体
type BeadItem struct {
    BeadID     string
    Name       string
    Material   string
    ColorGroup string // red/green/purple/gold
    UnitPrice  float64
    Stock      int
}
 
 
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Backtracking Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/7/23 7:03
# User      :  geovindu
# Product   : GoLand
# Project   : goalgorithms
# File      : jewelry.go
*/
package dto
 
// JewelryItem 成套首饰商品
type JewelryItem struct {
    SkuID    string
    Name     string
    Category string // necklace / earring / bracelet / ring
    Material string // Au999 / 18K / S925
    Color    string
    Style    string
    Price    float64
    Stock    int
    HasGem   bool
}
 
 
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Backtracking Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/7/23 7:04
# User      :  geovindu
# Product   : GoLand
# Project   : goalgorithms
# File      : bracelet_rule.go
*/
package rule
 
import "goalgorithms/backtracking/dto"
 
// BraceletRule 手串搭配约束
type BraceletRule struct {
    MaxSingleColor int
}
 
func (r *BraceletRule) Check(item dto.BeadItem, path []dto.BeadItem) bool {
    // 1.库存校验
    used := 0
    for _, p := range path {
        if p.BeadID == item.BeadID {
            used++
        }
    }
    if used >= item.Stock {
        return false
    }
 
    // 2.色系均衡限制
    colorCnt := make(map[string]int)
    for _, b := range path {
        colorCnt[b.ColorGroup]++
    }
    if colorCnt[item.ColorGroup] >= r.MaxSingleColor {
        return false
    }
    return true
}
 
 
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Backtracking Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/7/23 7:04
# User      :  geovindu
# Product   : GoLand
# Project   : goalgorithms
# File      : scene_jewelry_rule.go
*/
package rule
 
import "goalgorithms/backtracking/dto"
 
// SceneConfig 场景配置
type SceneConfig struct {
    AllowMaterial map[string]bool
    MustGem       bool
}
 
// SceneJewelryRule 场景首饰规则
type SceneJewelryRule struct {
    conf SceneConfig
}
 
func NewSceneJewelryRule(conf SceneConfig) *SceneJewelryRule {
    return &SceneJewelryRule{conf: conf}
}
 
func (r *SceneJewelryRule) Check(item dto.JewelryItem, path []dto.JewelryItem) bool {
    if item.Stock <= 0 {
        return false
    }
    if !r.conf.AllowMaterial[item.Material] {
        return false
    }
    if r.conf.MustGem && !item.HasGem {
        return false
    }
    return true
}
 
// GetSceneConfig 场景配置中心,新增场景只在这里扩展
func GetSceneConfig(sceneType string) SceneConfig {
    sceneMap := map[string]SceneConfig{
        "wedding": {
            AllowMaterial: map[string]bool{"Au999": true, "18K": true},
            MustGem:       true,
        },
        "commute": {
            AllowMaterial: map[string]bool{"Au999": true, "S925": true, "18K": true},
            MustGem:       false,
        },
        "dinner": {
            AllowMaterial: map[string]bool{"18K": true},
            MustGem:       true,
        },
    }
    cfg, ok := sceneMap[sceneType]
    if !ok {
        return sceneMap["commute"]
    }
    return cfg
}
 
 
 
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Backtracking Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/7/23 7:05
# User      :  geovindu
# Product   : GoLand
# Project   : goalgorithms
# File      : score_util.go
*/
package common
 
import "goalgorithms/backtracking/dto"
 
// ScoreBraceletScheme 手串方案评分
func ScoreBraceletScheme(scheme []dto.BeadItem) float64 {
    colorSet := make(map[string]bool)
    var totalCost float64
    for _, b := range scheme {
        colorSet[b.ColorGroup] = true
        totalCost += b.UnitPrice
    }
    diversity := float64(len(colorSet))
    return diversity*10 - totalCost/200
}
 
// ScoreJewelryScheme 成套首饰方案评分
func ScoreJewelryScheme(scheme []dto.JewelryItem) float64 {
    gemCnt := 0
    stockScore := 0
    for _, item := range scheme {
        if item.HasGem {
            gemCnt++
        }
        if item.Stock < 5 {
            stockScore += item.Stock
        } else {
            stockScore += 5
        }
    }
    return float64(gemCnt*5 + stockScore)
}
 
 
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Backtracking Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/7/23 7:05
# User      :  geovindu
# Product   : GoLand
# Project   : goalgorithms
# File      : backtrack_bracelet.go
*/
package core
 
import (
    "goalgorithms/backtracking/dto"
    "goalgorithms/backtracking/rule"
)
 
// BraceletBackTracker 手串回溯器
type BraceletBackTracker struct {
    beadPool  []dto.BeadItem
    rule      *rule.BraceletRule
    solutions [][]dto.BeadItem
}
 
func NewBraceletBackTracker(pool []dto.BeadItem, r *rule.BraceletRule) *BraceletBackTracker {
    return &BraceletBackTracker{
        beadPool: pool,
        rule:     r,
    }
}
 
func (bt *BraceletBackTracker) backtrack(path []dto.BeadItem, remain int, totalCost float64, budget float64) {
    if remain == 0 {
        cp := make([]dto.BeadItem, len(path))
        copy(cp, path)
        bt.solutions = append(bt.solutions, cp)
        return
    }
    if totalCost > budget {
        return
    }
 
    for _, bead := range bt.beadPool {
        if !bt.rule.Check(bead, path) {
            continue
        }
        path = append(path, bead)
        bt.backtrack(path, remain-1, totalCost+bead.UnitPrice, budget)
        path = path[:len(path)-1]
    }
}
 
func (bt *BraceletBackTracker) Run(targetCount int, budget float64) [][]dto.BeadItem {
    bt.solutions = make([][]dto.BeadItem, 0)
    bt.backtrack([]dto.BeadItem{}, targetCount, 0.0, budget)
    return bt.solutions
}
 
 
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Backtracking Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/7/23 7:06
# User      :  geovindu
# Product   : GoLand
# Project   : goalgorithms
# File      : backtrack_jewelry.go
*/
package core
 
import (
    "goalgorithms/backtracking/dto"
    "goalgorithms/backtracking/rule"
)
 
// JewelrySceneBackTracker 首饰成套回溯器
type JewelrySceneBackTracker struct {
    goodsPool []dto.JewelryItem
    rule      *rule.SceneJewelryRule
    solutions [][]dto.JewelryItem
}
 
func NewJewelrySceneBackTracker(pool []dto.JewelryItem, r *rule.SceneJewelryRule) *JewelrySceneBackTracker {
    return &JewelrySceneBackTracker{
        goodsPool: pool,
        rule:      r,
    }
}
 
func (bt *JewelrySceneBackTracker) backtrack(startIdx int, selected []dto.JewelryItem, totalPrice float64, budget float64, targetCategories map[string]bool) {
    // 判断是否集齐目标品类
    selectedCats := make(map[string]bool)
    for _, item := range selected {
        selectedCats[item.Category] = true
    }
    complete := true
    for cat := range targetCategories {
        if !selectedCats[cat] {
            complete = false
            break
        }
    }
    if complete {
        cp := make([]dto.JewelryItem, len(selected))
        copy(cp, selected)
        bt.solutions = append(bt.solutions, cp)
        return
    }
    if totalPrice > budget {
        return
    }
 
    for i := startIdx; i < len(bt.goodsPool); i++ {
        item := bt.goodsPool[i]
        if selectedCats[item.Category] {
            continue
        }
        if !bt.rule.Check(item, selected) {
            continue
        }
 
        selected = append(selected, item)
        bt.backtrack(i+1, selected, totalPrice+item.Price, budget, targetCategories)
        selected = selected[:len(selected)-1]
    }
}
 
func (bt *JewelrySceneBackTracker) Run(budget float64, targetCategories map[string]bool) [][]dto.JewelryItem {
    bt.solutions = make([][]dto.JewelryItem, 0)
    bt.backtrack(0, []dto.JewelryItem{}, 0.0, budget, targetCategories)
    return bt.solutions
}
 
 
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Backtracking Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/7/23 7:06
# User      :  geovindu
# Product   : GoLand
# Project   : goalgorithms
# File      : bracelet_service.go
*/
package service
 
import (
    "goalgorithms/backtracking/common"
    "goalgorithms/backtracking/core"
    "goalgorithms/backtracking/dto"
    "goalgorithms/backtracking/rule"
    "sort"
)
 
// BraceletMatchService 手串搭配业务服务
type BraceletMatchService struct {
    beadPool []dto.BeadItem
}
 
func NewBraceletMatchService(pool []dto.BeadItem) *BraceletMatchService {
    return &BraceletMatchService{beadPool: pool}
}
 
func (svc *BraceletMatchService) Match(targetCount int, budget float64, maxColorLimit int, topN int) [][]dto.BeadItem {
    r := &rule.BraceletRule{MaxSingleColor: maxColorLimit}
    tracker := core.NewBraceletBackTracker(svc.beadPool, r)
    schemes := tracker.Run(targetCount, budget)
 
    // 打分排序
    sort.Slice(schemes, func(i, j int) bool {
        return common.ScoreBraceletScheme(schemes[i]) > common.ScoreBraceletScheme(schemes[j])
    })
 
    if len(schemes) > topN {
        schemes = schemes[:topN]
    }
    return schemes
}
 
 
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Backtracking Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/7/23 7:07
# User      :  geovindu
# Product   : GoLand
# Project   : goalgorithms
# File      : jewelry_scene_service.go
*/
package service
 
import (
    "goalgorithms/backtracking/common"
    "goalgorithms/backtracking/core"
    "goalgorithms/backtracking/dto"
    "goalgorithms/backtracking/rule"
    "sort"
)
 
// JewelrySceneMatchService 场景首饰搭配服务
type JewelrySceneMatchService struct {
    goodsPool []dto.JewelryItem
}
 
func NewJewelrySceneMatchService(pool []dto.JewelryItem) *JewelrySceneMatchService {
    return &JewelrySceneMatchService{goodsPool: pool}
}
 
func (svc *JewelrySceneMatchService) MatchByScene(scene string, budget float64, targetCategories map[string]bool, topN int) [][]dto.JewelryItem {
    cfg := rule.GetSceneConfig(scene)
    r := rule.NewSceneJewelryRule(cfg)
    tracker := core.NewJewelrySceneBackTracker(svc.goodsPool, r)
    schemes := tracker.Run(budget, targetCategories)
 
    sort.Slice(schemes, func(i, j int) bool {
        return common.ScoreJewelryScheme(schemes[i]) > common.ScoreJewelryScheme(schemes[j])
    })
 
    if len(schemes) > topN {
        schemes = schemes[:topN]
    }
    return schemes
}

调用:

Go 复制代码
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Backtracking Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/7/23 7:07
# User      :  geovindu
# Product   : GoLand
# Project   : goalgorithms
# File      : backtrackingbll.go
*/
package bll
 
import (
    "fmt"
    "goalgorithms/backtracking/dto"
    "goalgorithms/backtracking/service"
)
 
func testBraceletMatch() {
    beadPool := []dto.BeadItem{
        {BeadID: "B01", Name: "南红圆珠", Material: "南红", ColorGroup: "red", UnitPrice: 168, Stock: 4},
        {BeadID: "B02", Name: "和田玉圆珠", Material: "和田玉", ColorGroup: "green", UnitPrice: 198, Stock: 5},
        {BeadID: "B03", Name: "紫水晶", Material: "紫水晶", ColorGroup: "purple", UnitPrice: 128, Stock: 4},
        {BeadID: "B04", Name: "足金隔珠", Material: "足金", ColorGroup: "gold", UnitPrice: 320, Stock: 3},
    }
    svc := service.NewBraceletMatchService(beadPool)
    result := svc.Match(8, 2000, 4, 6)
 
    fmt.Println("===== 多宝手串搭配方案 =====")
    for idx, scheme := range result {
        var total float64
        var names []string
        for _, b := range scheme {
            total += b.UnitPrice
            names = append(names, b.Name)
        }
        fmt.Printf("方案%d 总价:%.2f 珠子:%v\n", idx+1, total, names)
    }
}
 
func testJewelrySceneMatch() {
    goodsPool := []dto.JewelryItem{
        {SkuID: "N001", Name: "碎钻项链", Category: "necklace", Material: "18K", Color: "white", Style: "luxury", Price: 3299, Stock: 12, HasGem: true},
        {SkuID: "N003", Name: "素金项链", Category: "necklace", Material: "Au999", Color: "yellow", Style: "minimalist", Price: 2199, Stock: 9, HasGem: false},
        {SkuID: "E001", Name: "白钻耳饰", Category: "earring", Material: "18K", Color: "white", Style: "luxury", Price: 2199, Stock: 15, HasGem: true},
        {SkuID: "E003", Name: "素金耳饰", Category: "earring", Material: "Au999", Color: "yellow", Style: "minimalist", Price: 1399, Stock: 11, HasGem: false},
    }
    svc := service.NewJewelrySceneMatchService(goodsPool)
    targetCats := map[string]bool{"necklace": true, "earring": true}
 
    fmt.Println("\n===== 婚嫁场景 =====")
    wedding := svc.MatchByScene("wedding", 8000, targetCats, 8)
    for _, set := range wedding {
        var names []string
        var total float64
        for _, item := range set {
            names = append(names, item.Name)
            total += item.Price
        }
        fmt.Printf("%v 总价 %.2f\n", names, total)
    }
 
    fmt.Println("\n===== 通勤场景 =====")
    commute := svc.MatchByScene("commute", 5000, targetCats, 8)
    for _, set := range commute {
        var names []string
        var total float64
        for _, item := range set {
            names = append(names, item.Name)
            total += item.Price
        }
        fmt.Printf("%v 总价 %.2f\n", names, total)
    }
}
 
func BacktrackingMain() {
    testBraceletMatch()
    testJewelrySceneMatch()
}

介绍了一个基于回溯算法的珠宝搭配系统实现,主要包含:

  1. 数据结构定义:BeadItem(手串珠子)和JewelryItem(成套首饰)的实体结构
  2. 规则引擎:BraceletRule(手串搭配约束)和SceneJewelryRule(场景首饰规则)
  3. 回溯算法核心:分别实现了手串搭配和场景首饰搭配的回溯算法
  4. 服务层:提供BraceletMatchService和JewelrySceneMatchService业务服务
  5. 评分系统:根据颜色多样性、库存状况等指标对搭配方案进行评分排序

系统支持特定场景(婚嫁、通勤等)的珠宝搭配推荐,并考虑预算、库存等约束条件,最终输出按评分排序的TopN推荐方案。

输出:

相关推荐
qq_452396231 小时前
第六篇:《并发编程核心:Goroutine 与 Channel》
golang
ZDQNFU1 小时前
ORM之SQLAlchemy教程
后端·python
微露清风1 小时前
模拟算法学习记录
学习·算法
Assby1 小时前
为什么我不建议你在 MySQL 里写 `IN (超过1000个ID)`?从 AST 解析到存储引擎的深度拆解
后端·面试
用户40966601317511 小时前
从 MyBatis 到 JPA:一个 CRUD 程序员的认知重建
后端
lzhdim1 小时前
C# 中读取CPU、硬盘和内存温度
开发语言·c#
Irene19911 小时前
Oracle PL/SQL Developer 版本差异(11g、14)实战总结
java·开发语言
qq_448011162 小时前
C语言中的getchar()
c语言·开发语言
肖志-AI全栈2 小时前
JavaScript 快速排序:从 pivot、双指针到分治思想
开发语言·javascript·排序算法