/// <summary> /// Constructor for a candidate solution. /// </summary> /// <param name="items">List of all the items</param> /// <param name="index">index (into the above list) of the last item to be added to this candidate solution</param> /// <param name="previous">the remaining items</param> public CandidateSolution(List <KnapsackItem> items, int index, CandidateSolution previous) { if (index == -1) { _index = index; _value = 0; _weight = 0; _previous = null; } else { _index = index; _value = previous.Value + items[index].Value; _weight = previous.Weight + items[index].Weight; _previous = previous; } }
/// <summary> /// A method to compute the upper bound /// </summary> /// <param name="toCompute">The candidate solution whose upper bound we wish to compute</param> /// <param name="foundSoFar">The best candidate solution we have found so far</param> /// <returns>the upper bound</returns> public int ComputeBounds(CandidateSolution toCompute, ref CandidateSolution best) { int i = toCompute.Index + 1; while (i < _items.Count && (toCompute.Weight + _items[i].Weight) <= _weightLimit) { CandidateSolution newSolution = new CandidateSolution(_items, i, toCompute); toCompute = newSolution; i++; } if (toCompute.Value > best.Value) { best = toCompute; } if (i >= _items.Count || toCompute.Weight == _weightLimit) { return(toCompute.Value); } else { return((int)(((((long)(_weightLimit - toCompute.Weight) * (_items[i].Value)) - 1) / (_items[i].Weight)) + toCompute.Value)); } }
/// <summary> /// Method to find the optimal solution /// </summary> /// <param name="filename">input file</param> public void Solve(string filename) { _weightLimit = ReadInput(filename); CandidateSolution candidate = new CandidateSolution(_items, -1, null); CandidateSolution best = candidate; PriorityQueue <int, CandidateSolution> queue = new PriorityQueue <int, CandidateSolution>(); queue.Add(candidate, ComputeBounds(candidate, ref best)); while (queue.Count > 0 && queue.MaximumPriority >= best.Value) { CandidateSolution root = queue.RemoveMaximumPriority(); int k = root.Index + 1; for (int j = k; j < _items.Count; j++) { CandidateSolution child = new CandidateSolution(_items, j, root); if (child.Weight <= _weightLimit) { int childBounds = ComputeBounds(child, ref best); if (childBounds > best.Value) { queue.Add(child, childBounds); } } } } _totalValue = best.Value; _totalWeight = best.Weight; while (best.Previous != null) { KnapsackItem tmp = _items[best.Index]; tmp.SelectionText = "X"; _items[best.Index] = tmp; best = best.Previous; } }