项目结构:

/*# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述: Backtracking Algorithm
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/10 21:16
# User : geovindu
# Product : Visual Studio 2026
# Project : DesignAlgorithm
# File : BeadItem.cs*/
using System;
using System.Collections.Generic;
using System.Text;namespace CSharpAlgorithms.Backtracking.Dto
{/// <summary>/// 多宝手串珠子实体/// </summary>public class BeadItem{public string BeadId { get; set; } = string.Empty;public string Name { get; set; } = string.Empty;public string Material { get; set; } = string.Empty;public string ColorGroup { get; set; } = string.Empty; // red/green/purple/goldpublic double UnitPrice { get; set; }public int Stock { get; set; }}
}/*# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述: Backtracking Algorithm
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/10 21:16
# User : geovindu
# Product : Visual Studio 2026
# Project : DesignAlgorithm
# File : JewelryItem.cs*/
using System;
using System.Collections.Generic;
using System.Text;namespace CSharpAlgorithms.Backtracking.Dto
{/// <summary>/// 成套首饰商品/// </summary>public class JewelryItem{public string SkuId { get; set; } = string.Empty;public string Name { get; set; } = string.Empty;public string Category { get; set; } = string.Empty; // necklace / earringpublic string Material { get; set; } = string.Empty;public string Color { get; set; } = string.Empty;public string Style { get; set; } = string.Empty;public double Price { get; set; }public int Stock { get; set; }public bool HasGem { get; set; }}
}/*# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述: Backtracking Algorithm
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/10 21:16
# User : geovindu
# Product : Visual Studio 2026
# Project : DesignAlgorithm
# File : IBaseRule.cs*/using System;
using System.Collections.Generic;
using System.Text;namespace CSharpAlgorithms.Backtracking.Rule
{/// <summary>/// 规则抽象接口/// </summary>/// <typeparam name="T">物料类型 BeadItem / JewelryItem</typeparam>public interface IBaseRule<T>{bool Check(T item, List<T> path);}
}/*# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述: Backtracking Algorithm
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/10 21:16
# User : geovindu
# Product : Visual Studio 2026
# Project : DesignAlgorithm
# File : BraceletRule.cs*/using CSharpAlgorithms.Backtracking.Dto;
using System;
using System.Collections.Generic;
using System.Text;namespace CSharpAlgorithms.Backtracking.Rule
{public class BraceletRule : IBaseRule<BeadItem>{public int MaxSingleColor { get; }public BraceletRule(int maxSingleColor){MaxSingleColor = maxSingleColor;}public bool Check(BeadItem item, List<BeadItem> path){// 库存校验int used = path.Count(x => x.BeadId == item.BeadId);if (used >= item.Stock)return false;// 色系均衡限制Dictionary<string, int> colorCnt = new();foreach (var b in path){if (!colorCnt.ContainsKey(b.ColorGroup))colorCnt[b.ColorGroup] = 0;colorCnt[b.ColorGroup]++;}if (colorCnt.TryGetValue(item.ColorGroup, out var count) && count >= MaxSingleColor)return false;return true;}}
}/*# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述: Backtracking Algorithm
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/10 21:16
# User : geovindu
# Product : Visual Studio 2026
# Project : DesignAlgorithm
# File : SceneJewelryRule.cs*/using CSharpAlgorithms.Backtracking.Dto;
using System;
using System.Collections.Generic;
using System.Text;namespace CSharpAlgorithms.Backtracking.Rule
{public class SceneConfig{public HashSet<string> AllowMaterial { get; set; } = new();public bool MustGem { get; set; }}public class SceneJewelryRule : IBaseRule<JewelryItem>{private readonly SceneConfig _config;public SceneJewelryRule(SceneConfig config){_config = config;}public bool Check(JewelryItem item, List<JewelryItem> path){if (item.Stock <= 0)return false;if (!_config.AllowMaterial.Contains(item.Material))return false;if (_config.MustGem && !item.HasGem)return false;return true;}/// <summary>/// 场景配置中心,新增场景只在此扩展/// </summary>/// <param name="sceneType"></param>/// <returns></returns>public static SceneConfig GetSceneConfig(string sceneType){var map = new Dictionary<string, SceneConfig>(){{"wedding", new SceneConfig{AllowMaterial = new HashSet<string>{"Au999","18K"},MustGem = true}},{"commute", new SceneConfig{AllowMaterial = new HashSet<string>{"Au999","S925","18K"},MustGem = false}},{"dinner", new SceneConfig{AllowMaterial = new HashSet<string>{"18K"},MustGem = true}}};if (map.TryGetValue(sceneType, out var cfg))return cfg;return map["commute"];}}
}/*# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述: Backtracking Algorithm
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/10 21:16
# User : geovindu
# Product : Visual Studio 2026
# Project : DesignAlgorithm
# File : ScoreUtil.cs*/using CSharpAlgorithms.Backtracking.Dto;
using System;
using System.Collections.Generic;
using System.Text;namespace CSharpAlgorithms.Backtracking.Common
{/// <summary>/// /// </summary>public static class ScoreUtil{/// <summary>/// 手串方案评分:色系多样性优先/// </summary>public static double ScoreBraceletScheme(List<BeadItem> scheme){HashSet<string> colorSet = new();double totalCost = 0;foreach (var b in scheme){colorSet.Add(b.ColorGroup);totalCost += b.UnitPrice;}double diversity = colorSet.Count;return diversity * 10 - totalCost / 200;}/// <summary>/// 成套首饰方案评分/// </summary>public static double ScoreJewelryScheme(List<JewelryItem> scheme){int gemCnt = 0;int stockScore = 0;foreach (var item in scheme){if (item.HasGem) gemCnt++;stockScore += Math.Min(item.Stock, 5);}return gemCnt * 5 + stockScore;}}
}/*# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述: Backtracking Algorithm
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/06 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : DesignAlgorithm
# File : BraceletBackTracker.cs*/using CSharpAlgorithms.Backtracking.Dto;
using CSharpAlgorithms.Backtracking.Rule;
using System;
using System.Collections.Generic;
using System.Text;namespace CSharpAlgorithms.Backtracking.Core
{public class BraceletBackTracker{private readonly List<BeadItem> _beadPool;private readonly IBaseRule<BeadItem> _rule;private readonly List<List<BeadItem>> _solutions = new();public BraceletBackTracker(List<BeadItem> beadPool, IBaseRule<BeadItem> rule){_beadPool = beadPool;_rule = rule;}private void Backtrack(List<BeadItem> path, int remain, double totalCost, double budget){if (remain == 0){_solutions.Add(new List<BeadItem>(path));return;}if (totalCost > budget)return;foreach (var bead in _beadPool){if (!_rule.Check(bead, path))continue;path.Add(bead);Backtrack(path, remain - 1, totalCost + bead.UnitPrice, budget);path.RemoveAt(path.Count - 1);}}public List<List<BeadItem>> Run(int targetCount, double budget){_solutions.Clear();Backtrack(new List<BeadItem>(), targetCount, 0.0, budget);return _solutions;}}
}/*# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述: Backtracking Algorithm
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/06 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : DesignAlgorithm
# File : JewelrySceneBackTracker.cs*/using CSharpAlgorithms.Backtracking.Dto;
using CSharpAlgorithms.Backtracking.Rule;
using System;
using System.Collections.Generic;
using System.Text;namespace CSharpAlgorithms.Backtracking.Core
{/// <summary>/// /// </summary>public class JewelrySceneBackTracker{private readonly List<JewelryItem> _goodsPool;private readonly IBaseRule<JewelryItem> _rule;private readonly List<List<JewelryItem>> _solutions = new();/// <summary>/// /// </summary>/// <param name="goodsPool"></param>/// <param name="rule"></param>public JewelrySceneBackTracker(List<JewelryItem> goodsPool, IBaseRule<JewelryItem> rule){_goodsPool = goodsPool;_rule = rule;}/// <summary>/// /// </summary>/// <param name="startIdx"></param>/// <param name="selected"></param>/// <param name="totalPrice"></param>/// <param name="budget"></param>/// <param name="targetCategories"></param>private void Backtrack(int startIdx, List<JewelryItem> selected, double totalPrice, double budget, HashSet<string> targetCategories){HashSet<string> selectedCats = selected.Select(x => x.Category).ToHashSet();// 是否集齐所有目标品类bool complete = targetCategories.All(selectedCats.Contains);if (complete){_solutions.Add(new List<JewelryItem>(selected));return;}if (totalPrice > budget)return;for (int i = startIdx; i < _goodsPool.Count; i++){var item = _goodsPool[i];if (selectedCats.Contains(item.Category))continue;if (!_rule.Check(item, selected))continue;selected.Add(item);Backtrack(i + 1, selected, totalPrice + item.Price, budget, targetCategories);selected.RemoveAt(selected.Count - 1);}}/// <summary>/// /// </summary>/// <param name="budget"></param>/// <param name="targetCategories"></param>/// <returns></returns>public List<List<JewelryItem>> Run(double budget, HashSet<string> targetCategories){_solutions.Clear();Backtrack(0, new List<JewelryItem>(), 0.0, budget, targetCategories);return _solutions;}}
}/*# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述: Backtracking Algorithm
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/06 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : DesignAlgorithm
# File : BraceletMatchService.cs*/using CSharpAlgorithms.Backtracking.Common;
using CSharpAlgorithms.Backtracking.Core;
using CSharpAlgorithms.Backtracking.Dto;
using CSharpAlgorithms.Backtracking.Rule;
using System;
using System.Collections.Generic;
using System.Text;namespace CSharpAlgorithms.Backtracking.Service
{/// <summary>/// /// </summary>public class BraceletMatchService{private readonly List<BeadItem> _beadPool;public BraceletMatchService(List<BeadItem> beadPool){_beadPool = beadPool;}public List<List<BeadItem>> Match(int targetCount, double budget, int maxColorLimit, int topN){IBaseRule<BeadItem> rule = new BraceletRule(maxColorLimit);var tracker = new BraceletBackTracker(_beadPool, rule);var schemes = tracker.Run(targetCount, budget);// 打分降序schemes.Sort((a, b) => ScoreUtil.ScoreBraceletScheme(b).CompareTo(ScoreUtil.ScoreBraceletScheme(a)));if (schemes.Count > topN)schemes = schemes.Take(topN).ToList();return schemes;}}
}/*# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述: Backtracking Algorithm
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/06 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : DesignAlgorithm
# File : JewelrySceneMatchService.cs*/using CSharpAlgorithms.Backtracking.Common;
using CSharpAlgorithms.Backtracking.Core;
using CSharpAlgorithms.Backtracking.Dto;
using CSharpAlgorithms.Backtracking.Rule;
using System;
using System.Collections.Generic;
using System.Text;namespace CSharpAlgorithms.Backtracking.Service
{/// <summary>/// /// </summary>public class JewelrySceneMatchService{private readonly List<JewelryItem> _goodsPool;/// <summary>/// /// </summary>/// <param name="goodsPool"></param>public JewelrySceneMatchService(List<JewelryItem> goodsPool){_goodsPool = goodsPool;}/// <summary>/// /// </summary>/// <param name="scene"></param>/// <param name="budget"></param>/// <param name="targetCategories"></param>/// <param name="topN"></param>/// <returns></returns>public List<List<JewelryItem>> MatchByScene(string scene, double budget, HashSet<string> targetCategories, int topN){var config = SceneJewelryRule.GetSceneConfig(scene);IBaseRule<JewelryItem> rule = new SceneJewelryRule(config);var tracker = new JewelrySceneBackTracker(_goodsPool, rule);var schemes = tracker.Run(budget, targetCategories);schemes.Sort((a, b) => ScoreUtil.ScoreJewelryScheme(b).CompareTo(ScoreUtil.ScoreJewelryScheme(a)));if (schemes.Count > topN)schemes = schemes.Take(topN).ToList();return schemes;}}
}
/*# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述: Backtracking Algorithm
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/06 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : DesignAlgorithm
# File : BacktrackingBll.cs*/using CSharpAlgorithms.Backtracking.Dto;
using CSharpAlgorithms.Backtracking.Service;
using System;
using System.Collections.Generic;
using System.Text;namespace CSharpAlgorithms.Bll
{/// <summary>/// /// </summary>public class BacktrackingBll{static void TestBraceletMatch(){var beadPool = new List<BeadItem>(){new BeadItem{BeadId = "B01", Name = "南红圆珠", Material = "南红", ColorGroup = "red", UnitPrice = 168, Stock = 4},new BeadItem{BeadId = "B02", Name = "和田玉圆珠", Material = "和田玉", ColorGroup = "green", UnitPrice = 198, Stock = 5},new BeadItem{BeadId = "B03", Name = "紫水晶", Material = "紫水晶", ColorGroup = "purple", UnitPrice = 128, Stock = 4},new BeadItem{BeadId = "B04", Name = "足金隔珠", Material = "足金", ColorGroup = "gold", UnitPrice = 320, Stock = 3},};var svc = new BraceletMatchService(beadPool);var result = svc.Match(targetCount: 8, budget: 2000, maxColorLimit: 4, topN: 6);Console.WriteLine("===== 多宝手串搭配方案 =====");for (int idx = 0; idx < result.Count; idx++){var scheme = result[idx];double total = scheme.Sum(x => x.UnitPrice);var names = scheme.Select(x => x.Name).ToList();Console.WriteLine($"方案{idx + 1} 总价:{total:F2} 珠子:[{string.Join(", ", names)}]");}}static void TestJewelrySceneMatch(){var goodsPool = new List<JewelryItem>(){new JewelryItem{SkuId="N001",Name="碎钻项链",Category="necklace",Material="18K",Color="white",Style="luxury",Price=3299,Stock=12,HasGem=true},new JewelryItem{SkuId="N003",Name="素金项链",Category="necklace",Material="Au999",Color="yellow",Style="minimalist",Price=2199,Stock=9,HasGem=false},new JewelryItem{SkuId="E001",Name="白钻耳饰",Category="earring",Material="18K",Color="white",Style="luxury",Price=2199,Stock=15,HasGem=true},new JewelryItem{SkuId="E003",Name="素金耳饰",Category="earring",Material="Au999",Color="yellow",Style="minimalist",Price=1399,Stock=11,HasGem=false},};var svc = new JewelrySceneMatchService(goodsPool);var targetCats = new HashSet<string> { "necklace", "earring" };Console.WriteLine("\n===== 婚嫁场景 =====");var wedding = svc.MatchByScene("wedding", 8000, targetCats, 8);foreach (var set in wedding){var names = set.Select(x => x.Name).ToList();double total = set.Sum(x => x.Price);Console.WriteLine($"[{string.Join(", ", names)}] 总价 {total:F2}");}Console.WriteLine("\n===== 通勤场景 =====");var commute = svc.MatchByScene("commute", 5000, targetCats, 8);foreach (var set in commute){var names = set.Select(x => x.Name).ToList();double total = set.Sum(x => x.Price);Console.WriteLine($"[{string.Join(", ", names)}] 总价 {total:F2}");}}/// <summary>/// /// </summary>public void Demo(){TestBraceletMatch();TestJewelrySceneMatch();}}
}
输出:
