/// <summary> /// Find the closest collection more than ValueThreshold. /// </summary> /// <param name="Items"></param> /// <param name="WeightThreshold"></param> /// <returns></returns> public static WeightNode FindItemCollectionWithMostMatchValue(IEnumerable <Item> Items, double WeightThreshold) { int i; int numOfMoreThanThreshold = 0; const int BEST_SOLUTION_NUM = 3; double maxWeight = 0.0; WeightNode dummy = new WeightNode() { _Value = 0.0, _Weight = 0.0 }; LinkedList <WeightNode> retList = new LinkedList <WeightNode>(); LinkedListNode <WeightNode> node = null; LinkedListNode <WeightNode> moreWeighNode = null; retList.AddLast(dummy); foreach (Item g in Items) { for (i = 0; i < g.Number; i++) { node = retList.Last; moreWeighNode = retList.Last; maxWeight = retList.Last.Value._Weight; while (node != null) { double totalWeight = node.Value._Weight + g.Weight; while (moreWeighNode != null) { if (Math.Abs(totalWeight - moreWeighNode.Value._Weight) < 0.001) { if (node.Value._Value + g.Value > moreWeighNode.Value._Value) { // employ the current node + the current grocery WeightNode wn = new WeightNode(node.Value); wn.AddItem(g); moreWeighNode.Value = wn; } break; } else if (totalWeight < moreWeighNode.Value._Weight) { moreWeighNode = moreWeighNode.Previous; } else if (totalWeight > moreWeighNode.Value._Weight) { if ((totalWeight < maxWeight) || (totalWeight < WeightThreshold) || ((totalWeight > WeightThreshold) && (numOfMoreThanThreshold < BEST_SOLUTION_NUM))) { WeightNode wn = new WeightNode(node.Value); wn.AddItem(g); retList.AddAfter(moreWeighNode, new LinkedListNode <WeightNode>(wn)); moreWeighNode = moreWeighNode.Next; if (totalWeight > WeightThreshold) { if (numOfMoreThanThreshold > BEST_SOLUTION_NUM) { retList.RemoveLast(); } else { numOfMoreThanThreshold++; } } maxWeight = retList.Last.Value._Weight; } break; } } node = node.Previous; } } } return(retList.First(o => (o._Weight >= WeightThreshold))); }
/// <summary> /// Select some grocery from Groceries and make sure /// 1. the total weight is less than MaxWeight /// 2. the total value is highest. /// /// </summary> /// <param name="Groceries"></param> /// <param name="MaxWeight"></param> /// <returns></returns> public static WeightNode Process(IEnumerable <Item> Groceries, double MaxWeight) { /* * (Value/Weight) * * retList * | * +- dummy (0.0/0.0) * | * +- WeightNode (V/W) --> Item0 -> Item1 -> ... -> ItemN * | * + ... * | * +- WeightNode (V/Capacity) -> Item0 -> Item1 -> ... ItemN * */ int i; WeightNode dummy = new WeightNode() { _Value = 0.0, _Weight = 0.0 }; LinkedList <WeightNode> retList = new LinkedList <WeightNode>(); LinkedListNode <WeightNode> node = null; LinkedListNode <WeightNode> moreWeighNode = null; retList.AddLast(dummy); foreach (Item g in Groceries) { for (i = 0; i < g.Number; i++) { node = retList.Last; moreWeighNode = retList.Last; while (node != null) { double totalWeight = node.Value._Weight + g.Weight; if (totalWeight <= MaxWeight) { while (moreWeighNode != null) { if (Math.Abs(totalWeight - moreWeighNode.Value._Weight) < 0.001) { if (node.Value._Value + g.Value > moreWeighNode.Value._Value) { // employ the current node + the current grocery WeightNode wn = new WeightNode(node.Value); wn.AddItem(g); moreWeighNode.Value = wn; } break; } else if (totalWeight < moreWeighNode.Value._Weight) { moreWeighNode = moreWeighNode.Previous; } else if (totalWeight > moreWeighNode.Value._Weight) { WeightNode wn = new WeightNode(node.Value); wn.AddItem(g); //moreWeighNode.AddGrocery(g); retList.AddAfter(moreWeighNode, new LinkedListNode <WeightNode>(wn)); moreWeighNode = moreWeighNode.Next; break; } } } node = node.Previous; } } } double maxValue = retList.Max(o => o._Value); return(retList.Last(o => (o._Value == maxValue))); }