/// <summary>
        ///     Метод поска с возвратом
        ///     При поиске не добавляются в стек плохие направления
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void branchesAndBoundsAndReturn_Click(object sender, EventArgs e)
        {
            var count        = dataGridView1.Rows.Count;
            var sources      = new string[count];
            var destinations = new string[count];
            var prices       = new double[count];
            var cities       = new List <string>();

            for (var index = 0; index < count; index++)
            {
                sources[index]      = Convert.ToString(dataGridView1[0, index].EditedFormattedValue);
                destinations[index] = Convert.ToString(dataGridView1[1, index].EditedFormattedValue);
                prices[index]       = Convert.ToDouble(dataGridView1[2, index].EditedFormattedValue);
                cities.Add(sources[index]);
                cities.Add(destinations[index]);
            }
            cities = cities.Distinct().ToList();

            var stack = new Stack <BranchesAndBoundsPlan>();
            var zero  = new BranchesAndBoundsPlan();

            zero.MinCount = 0;
            zero.MaxCount = count;
            zero.MinPrice = 0;
            zero.MaxPrice = prices.Sum();
            stack.Push(zero);
            var foundPrice = double.MaxValue;
            var foundPlan  = zero;

            while (stack.Any())
            {
                var item = stack.Pop();
                do
                {
                    if (item.bools.Count == count)
                    {
                        var s = new List <string>();
                        var d = new List <string>();

                        for (var j = 0; j < count; j++)
                        {
                            if (item.bools.ContainsKey(j) && item.bools[j])
                            {
                                s.Add(sources[j]);
                                d.Add(destinations[j]);
                            }
                        }
                        if (item.MaxPrice <= foundPrice && s.Count == cities.Count && IsCyclic(s, d))
                        {
                            foundPrice = item.MaxPrice;
                            foundPlan  = item;
                        }
                        item = null;
                    }
                    else
                    {
                        var b = new BranchesAndBoundsPlan();
                        foreach (var pair in item.bools)
                        {
                            b.bools.Add(pair.Key, pair.Value);
                        }
                        var index = b.bools.Count;
                        b.bools.Add(index, true);
                        b.MaxCount = item.MaxCount;
                        b.MinCount = item.MinCount + 1;
                        b.MaxPrice = item.MaxPrice;
                        b.MinPrice = item.MinPrice + prices[index];
                        if (b.MaxCount >= cities.Count && b.MinPrice <= foundPrice)
                        {
                            stack.Push(b);                                                         // отсечение границей
                        }
                        index = item.bools.Count;
                        item.bools.Add(index, false);
                        item.MaxCount -= 1;
                        item.MaxPrice -= prices[index];
                    }
                } while (item != null);
            }
            for (var index = 0; index < count; index++)
            {
                dataGridView1[3, index].Value = foundPlan.bools[index];
            }
            UpdateTotal();
            SystemSounds.Beep.Play();
        }
        private void branchesAndBounds_Click(object sender, EventArgs e)
        {
            var count        = dataGridView1.Rows.Count;
            var sources      = new string[count];
            var destinations = new string[count];
            var prices       = new double[count];
            var foundPrice   = double.MaxValue;
            var cities       = new List <string>();

            for (var index = 0; index < count; index++)
            {
                sources[index]      = Convert.ToString(dataGridView1[0, index].EditedFormattedValue);
                destinations[index] = Convert.ToString(dataGridView1[1, index].EditedFormattedValue);
                prices[index]       = Convert.ToDouble(dataGridView1[2, index].EditedFormattedValue);
                cities.Add(sources[index]);
                cities.Add(destinations[index]);
            }
            cities = cities.Distinct().ToList();
            var list  = new List <BranchesAndBoundsPlan>();
            var list2 = new List <BranchesAndBoundsPlan>();
            var zero  = new BranchesAndBoundsPlan
            {
                MinCount = 0,
                MinPrice = 0,
                MaxCount = dataGridView1.Rows.Count,
                MaxPrice = prices.Sum()
            };

            list.Add(zero);
            for (var index = 0; index <= count; index++)
            {
                var list1 = new List <BranchesAndBoundsPlan>();
                foreach (var item in list)
                {
                    var s = new List <string>();
                    var d = new List <string>();

                    for (var j = 0; j < count; j++)
                    {
                        if (item.bools.ContainsKey(j) && item.bools[j])
                        {
                            s.Add(sources[j]);
                            d.Add(destinations[j]);
                        }
                    }
                    if (s.Count == cities.Count && IsCyclic(s, d))
                    {
                        var price = 0.0;
                        for (var j = 0; j < dataGridView1.Rows.Count; j++)
                        {
                            if (item.bools.ContainsKey(j) && item.bools[j])
                            {
                                price += prices[j];
                            }
                        }
                        foundPrice = Math.Min(foundPrice, price);
                        list2.Add(item);
                    }
                    else if (index < count)
                    {
                        var a = new BranchesAndBoundsPlan();
                        foreach (var pair in item.bools)
                        {
                            a.bools.Add(pair.Key, pair.Value);
                        }
                        a.bools.Add(index, false);
                        a.MaxCount = item.MaxCount - 1;
                        a.MinCount = item.MinCount;
                        a.MaxPrice = item.MaxPrice - prices[index];
                        a.MinPrice = item.MinPrice;
                        if (a.MaxCount >= cities.Count)
                        {
                            list1.Add(a);
                        }

                        var b = new BranchesAndBoundsPlan();
                        foreach (var pair in item.bools)
                        {
                            b.bools.Add(pair.Key, pair.Value);
                        }
                        b.bools.Add(index, true);
                        b.MaxCount = item.MaxCount;
                        b.MinCount = item.MinCount + 1;
                        b.MaxPrice = item.MaxPrice;
                        b.MinPrice = item.MinPrice + prices[index];
                        if (b.MinCount <= cities.Count)
                        {
                            list1.Add(b);
                        }
                        textBox3.Text += string.Format("Memory: {0} items" + Environment.NewLine, list.Sum(i => 1 + i.bools.Count) + list1.Sum(i => 1 + i.bools.Count));
                    }
                }
                list           = list1.Where(i => i.MinPrice <= foundPrice).ToList();
                textBox3.Text += string.Format("Memory: {0} items" + Environment.NewLine, list.Sum(i => 1 + i.bools.Count));
            }
            if (!list2.Any())
            {
                return;
            }
            var z = list2.First(i => Math.Abs(i.MinPrice - foundPrice) < 0.001);

            for (var index = 0; index < dataGridView1.Rows.Count; index++)
            {
                dataGridView1[3, index].Value = z.bools.ContainsKey(index) && z.bools[index];
            }
            UpdateTotal();
            SystemSounds.Beep.Play();
        }