protected void CalcTotalDist(VrpData data, VrpResult result)
        {
            double totalDist = 0;
            foreach (var route in result.Routes)
            {
                for (int i = 0; i < route.Count - 1; i++)
                {
                    totalDist += data.Customers[route[i]].Point.Dist(data.Customers[route[i + 1]].Point);
                }
            }

            result.Dist = totalDist;
        }
        protected static void ApplyTsp(VrpData data, VrpResult result)
        {
            var tspSolver = new Opt2();
            for (int i = 0; i < data.V; i++)
            {
                var route = result.Routes[i];
                if (route.Count > 4)
                {
                    route.RemoveAt(route.Count - 1);
                    var measure =
                        new MatrixMeasureFactory().CreateMatrixMeasure(route.Select(x => data.Customers[x].Point).ToArray());
                    var tspRoute = tspSolver.GetPath(route.Count, measure);

                    int startIndex = 0;
                    for (int j = 0; j < tspRoute.Length; j++)
                    {
                        if (tspRoute[j] == 0)
                        {
                            startIndex = j;
                            break;
                        }
                    }
                    result.Routes[i] = new List<int>();
                    for (int j = startIndex; j < tspRoute.Length; j++)
                    {
                        result.Routes[i].Add(route[tspRoute[j]]);
                    }
                    for (int j = 0; j < startIndex; j++)
                    {
                        result.Routes[i].Add(route[tspRoute[j]]);
                    }
                    result.Routes[i].Add(0);
                }
                else
                {
                    result.Routes[i] = route;
                }
            }
        }
        public override VrpResult Solve(VrpData data)
        {
            var sortedCustomers = data.Customers.OrderByDescending(c => c.Demand).ToArray();

            var result = new VrpResult();
            result.Routes = new List<int>[data.V];
            var n = data.N;
            var v = data.V;
            var used = new bool[n];
            used[0] = true;

            for (int i = 0; i < v; i++)
            {
                var route = new List<int> { 0 };

                var cap = data.C;
                foreach (var customer in sortedCustomers.Where(c => !used[c.Id]).ToList())
                {
                    if (customer.Demand <= cap)
                    {
                        cap -= customer.Demand;
                        route.Add(customer.Id);
                        used[customer.Id] = true;
                    }
                }

                route.Add(0);
                result.Routes[i] = route;
            }

            ApplyTsp(data, result);

            CalcTotalDist(data, result);

            return result;
        }
        private void GetPath()
        {
            if (_vrpData == null)
            {
                return;
            }

            _vrpResult = _solver.Solve(_vrpData);
        }
        public override VrpResult Solve(VrpData data)
        {
            VrpResult bestResult = null;
            var timelimit = BaseTimelimit;
            var stopwatch = Stopwatch.StartNew();

            /*var rnd = new Random();

            var pr = new double[data.V];
            for (int i = 0; i < data.V; i++)
            {
                pr[i] = 1D / (data.V - 1);
            }
            pr[0] = 0;*/

            while (true)
            {
                stopwatch.Stop();
                if (bestResult != null && (bestResult.Dist < 1400 || stopwatch.ElapsedMilliseconds > timelimit))
                {
                    break;
                }
                stopwatch.Start();

                /*var r = rnd.NextDouble() * pr.Sum();
                var sum = 0D;
                var v = 2;
                for (int i = 0; i < data.V; i++)
                {
                    sum += pr[i];
                    if (sum > r)
                    {
                        v = i + 1;
                        break;
                    }
                }*/
                var v = data.V;

                var baseClusters = GetKmeanClusters(data, v);

                var found = UpdateClustersBurn(data, baseClusters, v);

                if (!found)
                {
                    //pr[v - 1] /= 2;
                    continue;
                }

                var result = new VrpResult();
                result.Routes = new List<int>[data.V];
                for (int i = 0; i < data.V; i++)
                {
                    result.Routes[i] = new List<int> { 0 };
                }
                for (int i = 1; i < data.N; i++)
                {
                    result.Routes[baseClusters.Color[i]].Add(i);
                }
                for (int i = 0; i < data.V; i++)
                {
                    result.Routes[i].Add(0);
                }

                ApplyTsp(data, result);
                CalcTotalDist(data, result);

                if (bestResult == null || bestResult.Dist > result.Dist)
                {
                    //pr[v - 1] *= (1 << (data.V - v));
                    bestResult = result;
                }
            }

            return bestResult;
        }