Esempio n. 1
0
        public void Calc(Good[] goods)
        {
            _goods = goods;
            _matrix = new int[_maxWeight + 1, _goodsCount]; //Реализуем массив функции

            //Реализуем алгоритм Беллмана
            for (int weight = 1; weight <= _maxWeight; weight++) // Загружаем рюкзак если его вместимость = Weight
                for (int i = 1; i < _goodsCount; i++) // берем предметы с 1 по goodsCount
                    //если вес предмета больше Weight, или предыдущий набор лучше выбираемого
                    if (goods[i].Weight > weight)
                    {
                        _matrix[weight, i] = _matrix[weight, i - 1]; //тогда берем предыдущий набор
                        goods[i].IsTaken = false;
                    }
                    else if (_matrix[weight, i - 1] >= (_matrix[weight - goods[i].Weight, i - 1] + goods[i].Price))
                    {
                        _matrix[weight, i] = _matrix[weight, i - 1]; //тогда берем предыдущий набор
                        goods[i].IsTaken = false;
                    }
                    else
                    {
                        _matrix[weight, i] = _matrix[weight - goods[i].Weight, i - 1] + goods[i].Price; //иначе добавляем к предыдущему набору текущий предмет
                        goods[i].IsTaken = true;
                    }
        }
Esempio n. 2
0
 public void PrintGoods(Good[] goods)
 {
     var sb = new StringBuilder();
     foreach (var good in goods)
     {
         sb.AppendFormat("{0}:{1}{2}", good.Price, good.Weight, "|");
     }
     Console.Write(sb.ToString(0, sb.Length - 1));
 }
Esempio n. 3
0
        public void Calc(Good[] goods)
        {
            var groupsCapacity = GetGroupsCapacity(goods);
            //сортируем товары по убыванию цены
            var goodsByPrice = goods.OrderByDescending(g => g.Price);
            Dictionary<int, GoodsPack> bestPacks = new Dictionary<int, GoodsPack>();
            //идем от мин-групп к маскимальным
            for (int groupRang = groupsCapacity.MinElementsCount; groupRang <= groupsCapacity.MaxElementsCount; groupRang++)
            {
                //берем n элементов с макс ценами (n - вместимость группы)
                Good[] mostExpensiveGoods = goodsByPrice.Take(groupRang).ToArray();
                //считаем веса, если общий вес > вместимости рюкзака, решаем какой элемент нужно откинуть из группы (иначе оптимальная группа найдена)
                if (mostExpensiveGoods.Sum(g => g.Weight) <= _bagMaxWeight)
                {
                    GoodsPack bestPack = CreatePack(mostExpensiveGoods);
                    bestPacks.Add(groupRang, bestPack);
                    continue;
                }

                //алгоритм выбора элемента для замены:

                var firstOutOfGroupElement = goodsByPrice.ElementAtSafe(groupRang);
                if (firstOutOfGroupElement == null)
                {
                    bestPacks.Add(groupRang, new GoodsPack());
                    continue;
                }

                if (SubstituteElement(mostExpensiveGoods, firstOutOfGroupElement))
                {
                    GoodsPack bestPack = CreatePack(mostExpensiveGoods);
                    bestPacks.Add(groupRang, bestPack);
                    continue;
                }

                GoodsPack pack = CalcBestPackAlg(goodsByPrice, mostExpensiveGoods, firstOutOfGroupElement);
                bestPacks.Add(groupRang, pack);

                //Увеличиваем разрядность анализируемой группы
            }

            var packs = bestPacks.Values;
            var maxPackPrice = packs.Max(p => p.Price);
            BestPriceGoodsPack = packs.First(p => p.Price == maxPackPrice);
        }
Esempio n. 4
0
        //Вычисляем дельту весов и дельту цены по каждой парах  [ElementInGroup(i) - firstOutOfGroupElement], firstOutOfGroupElement - secondOutOfGroupElement
        //Выбираем мин дельту цены, такую что дельта весов > 0 (вес уменьшится);
        private GoodsPack CalcBestPackAlg(IOrderedEnumerable<Good> goodsByPrice, Good[] mostExpensiveGoods, Good firstOutOfGroupElement)
        {
            //Решаем переходить к следующему внегрупповому элементу или делать подстановку с целью уменьшения веса группы.
            //Для решения сравниваем выигрыш в весе группы, если
            //1) Заменим i-ый элемент, - всего n разниц
            //2) Перейдем к следующему элементу вне группы, =  Вес (n+1) элемента - вес (n+2) элемента

            var currentOutOfGroupElement = firstOutOfGroupElement;
            currentOutOfGroupElement.Index = mostExpensiveGoods.Length;

            while (currentOutOfGroupElement != null)
            {
                foreach (var good in mostExpensiveGoods)
                {
                    good.DeltaWeight = good.Weight - firstOutOfGroupElement.Weight;
                }

                var nextOutOfGroupElement = goodsByPrice.ElementAtSafe(currentOutOfGroupElement.Index + 1);
                if (nextOutOfGroupElement == null)
                {
                    currentOutOfGroupElement.DeltaWeight = int.MinValue;
                }
                else
                {
                    nextOutOfGroupElement.Index = currentOutOfGroupElement.Index + 1;
                }
                var allElements = new List<Good>(mostExpensiveGoods.Length + 1);
                allElements.AddRange(mostExpensiveGoods);
                allElements.Add(currentOutOfGroupElement);
                var maxDeltaWeight = allElements.Max(el => el.DeltaWeight);
                var mostPriorityByWeightElement = allElements.OrderByDescending(el => el.Price).First(e => e.DeltaWeight == maxDeltaWeight);
                if (mostPriorityByWeightElement.Index < mostExpensiveGoods.Length)
                {//значит нужно сделать ракировку элемента группы с элементом вне группы
                    mostExpensiveGoods[mostPriorityByWeightElement.Index] = currentOutOfGroupElement;
                }

                if (mostExpensiveGoods.Sum(g => g.Price) <= _bagMaxWeight)
                {//Как только найдена группа с суммой элементов < вместимости рюкзака, группаз разрядности n считается найеденнной
                    return CreatePack(mostExpensiveGoods);
                }
                currentOutOfGroupElement = nextOutOfGroupElement;
            }
            return new GoodsPack(); // групп ранга n с  сумой весов < вместимости рюкзака - не существует
        }
Esempio n. 5
0
 private bool SubstituteElement(Good[] mostExpensiveGoods, Good outOfGroupElement)
 {
     //берем элемент вне группы с макс ценой, и пытаемся его вставить вместо каждого элемента группы (от меньш цены к большей),
     //если для всех комбинаций вес > вместимости рюкзаке, то группа не найдена (иначе группа найдена)
     for (int i = mostExpensiveGoods.Length - 1; i >= 0; i--)
     {
         var temp = mostExpensiveGoods[i];
         mostExpensiveGoods[i] = outOfGroupElement;
         if (mostExpensiveGoods.Sum(g => g.Weight) <= _bagMaxWeight)
         {
             return true;
         }
         mostExpensiveGoods[i] = temp;
     }
     return false;
 }
Esempio n. 6
0
        /// <summary>
        /// Посчитать группы какой вместимости возможны на переданном наборе элементов
        /// </summary>
        /// <param name="goods"></param>
        /// <returns></returns>
        private GroupsCapacity GetGroupsCapacity(Good[] goods)
        {
            //Отсортировать товары по весам
            //найти мин кол-во элементов в группе и максимальное кол-во элементов

            var goodsByWeightAsc = goods.OrderBy(g => g.Weight);
            int totalWeight = 0;
            var enumerator = goodsByWeightAsc.GetEnumerator();
            //calc max elements count
            GroupsCapacity capacity = new GroupsCapacity();
            //calc max elements count
            while (enumerator.MoveNext())
            {
                if (totalWeight + enumerator.Current.Weight > _bagMaxWeight)
                {
                    break;
                }
                totalWeight += enumerator.Current.Weight;
                capacity.MaxElementsCount++;
            }

            var goodsByWeightDesc =  goodsByWeightAsc.Reverse();
            enumerator = goodsByWeightDesc.GetEnumerator();
            //calc min elements count
            totalWeight = 0;
            while (enumerator.MoveNext())
            {
                if (totalWeight + enumerator.Current.Weight > _bagMaxWeight)
                {
                    break;
                }
                totalWeight += enumerator.Current.Weight;
                capacity.MinElementsCount++;
            }
            return capacity;
        }
Esempio n. 7
0
        public void Calc(Good[] goods)
        {
            int price;
            List<Good> bag = new List<Good>(); // это рюкзак
            List<string> goodNames = new List<string>(); // буфер id
            List<string> prices = new List<string>(); // список цен коллекций
            Random random = new Random();
            Good good;
            int weightTotal = 0;
            int priceTotal = 0;
            string idLine = "";
            int errorCount = 0;

            startLoop:
            bag.Clear();
            nextAdd:
            // добавление предметов в рюкзак в разном порядке
            good = goods[random.Next(0, Convert.ToInt32(goods.Length))];
            if (!bag.Contains(good))
                bag.Add(good);
            else
                goto nextAdd;
            weightTotal = 0;
            // проверка общего веса
            foreach (Good item in bag)
            {
                weightTotal += item.Weight;
            }
            if (weightTotal < _bagMaxWeight)
                goto nextAdd;
            else
            {
                for (int i = 0; ; i++)
                {
                    if (weightTotal <= _bagMaxWeight) break;
                    else
                    {
                        bag.RemoveAt(Convert.ToInt32(bag.Count - 1));
                        // проверка общего веса
                        weightTotal = 0;
                        foreach (Good item in bag)
                        {
                            weightTotal += item.Weight;
                        }
                    }
                }
            }

            goodNames.Clear();
            priceTotal = 0;
            // подсчет общей цены коллекции
            foreach (Good item in bag)
            {
                price = item.Price;
                goodNames.Add(item.Name);
                priceTotal += price;
            }

            // сбор id в строку
            idLine = "";
            int count = 0;
            foreach (string i in goodNames)
            {
                if (count != (goodNames.Count - 1))
                    idLine += i + ",";
                else
                    idLine += i;
                count++;
            }

            if (!prices.Contains(Convert.ToString(priceTotal) + ";" + idLine))
            {
                var pack = new GoodsPack();
                pack.AddRange(bag);
                _goodsPacks.Add(pack);
                prices.Add(Convert.ToString(priceTotal) + ";" + idLine);
            }
            else
            {
                errorCount++;
                if (errorCount >= ((goods.Length) * (goods.Length))) goto countingPrice;
            }
            goto startLoop;

            countingPrice:
            var maximumPrice = _goodsPacks.Max(p => p.Price);
            BestPriceGoodsPack = _goodsPacks.First(p => p.Price == maximumPrice);
            BestPriceGoodsPack.SetTaken();
        }
Esempio n. 8
0
        private static Good[] Create3GoodsArray()
        {
            var goods = new Good[3];
            for (int i = 0; i < 3; i++)
            {
                string name = (i + 1).ToString();
                goods[i] = new Good(name);
            }

            goods[0].Weight = 20;
            goods[0].Price = 60;

            goods[1].Weight = 30;
            goods[1].Price = 90;

            goods[2].Weight = 50;
            goods[2].Price = 100;
            return goods;
        }
Esempio n. 9
0
        private static Good[] Create9GoodsArray()
        {
            var goods = new Good[9];
            for (int i = 0; i < 9; i++)
            {
                string name = (i + 1).ToString();
                goods[i] = new Good(name);
            }

            goods[0].Weight = 36;
            goods[0].Price = 68;

            goods[1].Weight = 18;
            goods[1].Price = 10;

            goods[2].Weight = 19;
            goods[2].Price = 50;

            goods[3].Weight = 23;
            goods[3].Price = 20;

            goods[4].Weight = 29;
            goods[4].Price = 65;

            goods[5].Weight = 32;
            goods[5].Price = 30;

            goods[6].Weight = 35;
            goods[6].Price = 60;

            goods[7].Weight = 44;
            goods[7].Price = 40;

            goods[8].Weight = 67;
            goods[8].Price = 70;
            return goods;
        }
Esempio n. 10
0
        static void MainBellmanAlg(string[] args)
        {
            int i, j; //просто переменные :)

            Console.WriteLine("Данная программа поможет Вам заполнить Ваш рюкзак максимально ценными товарами\nАвтор: Владимир Рыбалка");

            //Введем количество товаров
            do
            {
                incorrEnter = false;
                Console.Write("\nКакое количество товаров вы рассматриваете для приобретения: ");
                try
                {
                    _goodsCount = Convert.ToInt32(Console.ReadLine());
                }
                catch (FormatException)
                {
                    incorrEnter = true;
                    _goodsCount = 0;
                }
            } while (incorrEnter);

            var goods = new Good[_goodsCount]; //Создаем массив заданного размера

            //Создадим объекты товаров
            for (i = 0, j = i + 1; i < goods.Length; i++, j++)
            {
                Console.Write("\n\nВведите название " + j + "-го товара: ");
                _enteredName = Console.ReadLine();
                do
                {
                    incorrEnter = false;
                    Console.Write("Введите вес товара: ");
                    try
                    {
                        _enteredWeight = Convert.ToInt32(Console.ReadLine());
                    }
                    catch (FormatException)
                    {
                        incorrEnter = true;
                        _enteredWeight = 0;
                    }
                } while (incorrEnter);
                do
                {
                    incorrEnter = false;
                    Console.Write("Введите цену товара: ");
                    try
                    {
                        _enteredPrice = Convert.ToInt32(Console.ReadLine());
                    }
                    catch (FormatException)
                    {
                        incorrEnter = true;
                        _enteredPrice = 0;
                    }
                } while (incorrEnter);
                var good = new Good(_enteredName); //Создаем объект
                good.Weight = _enteredWeight;
                good.Price = _enteredPrice;
                goods[i] = good;
            }

            // Введем размер рюкзака
            do
            {
                incorrEnter = false;
                Console.Write("\nВведите размер вашего рюкзака (контейнера): ");
                try
                {
                    _bagMaxWeight = Convert.ToInt32(Console.ReadLine());
                }
                catch (FormatException)
                {
                    incorrEnter = true;
                    _bagMaxWeight = 0;
                }
            } while (incorrEnter);

            BellmanAlg alg = new BellmanAlg(_bagMaxWeight, _goodsCount);
            alg.Calc(goods);

            Print(goods, alg.BestPriceGoodsPack.Price);

            Console.ReadKey();
        }
Esempio n. 11
0
 // Метод выводит на экран рюкзак
 static void Print(Good[] goods, int maxPriceForGoodsPack)
 {
     Console.WriteLine("\nМаксимальная стоимость: " + maxPriceForGoodsPack);
     Console.Write("Взяты следующие предметы: ");
     foreach (Good good in goods)
         if (good.IsTaken)
             Console.Write(good.Name + " ");
 }