Пример #1
0
        public static Solution Solve(Input input)
        {
            var takenPictures = new List<Snapshot>();

            var tree = new KdTree<float, PicCollection>(2, new FloatMath());

            foreach (var picCollection in input.Collections)
            {
                foreach (var pict in picCollection.Locations)
                {
                    tree.Add(new float[] { pict.Lat, pict.Lon }, picCollection);
                }
            }
            tree.Balance();

            var orderedSatellelites = input.Satellites.OrderByDescending(sat => sat.MaxRot).ToList();

            for (int s = 0; s < orderedSatellelites.Count; ++s)
            {
                var satellite = orderedSatellelites[s];

                for (int turn = 0; turn < input.NbTurns; ++turn)
                {
                    var node = tree.RadialSearch(new float[] { satellite.Pos.Lat, satellite.Pos.Lon }, satellite.MaxRot*SQRT2, 150).ToArray();

                    if (node.Length > 0)
                    {
                        var valids = node.Where(n => n.Value.PictureCanBeTaken(turn))
                            .Where(k => satellite.CanTakePicture((int)k.Point[0], (int)k.Point[1]))
                            .OrderByDescending(k => Math.Pow(k.Point[0] - satellite.Pos.Lat, 2) + Math.Pow(k.Point[1] - satellite.Pos.Lon, 2))
                            //.OrderByDescending(k => k.Value.TakenPictures.Count)
                            .ToList();

                        if (valids.Count > 0)
                        {
                            Console.WriteLine("Found {0} valid new positions", valids.Count);

                            var pict = valids[0];
                            var pictCoord = new Coords((int)pict.Point[0], (int)pict.Point[1]);

                            var snap = satellite.TakePicture(pictCoord);
                            takenPictures.Add(snap);
                            pict.Value.TakePicture(pictCoord);
                            pict.Value.Locations.Remove(pictCoord);
                            tree.RemoveAt(pict.Point);
                            Console.WriteLine("Satellite {1} Found {0} pict - Turn {2}", node.Length, satellite.Id, turn);

                            ////Console.WriteLine("Satellite Lat {0} Lon {1} Pict {2} {3} Rot {4} {5}", satellite.Pos.Lat,
                            //satellite.Pos.Lon, pict.Point[0], pict.Point[1], satellite.CurrentRot.Lat, satellite.CurrentRot.Lon);
                        }

                    }
                    satellite.NextTurn();
                }
            }

            var score = input.Collections.Where(c => c.Locations.Count == 0 && c.TakenPictures.Count > 0).Sum(p => p.Value);

            var solution = new Solution(takenPictures, score);

            return solution;
        }
Пример #2
0
 public int TestScoreForTurn(int turn)
 {
     var s = new Solution(new Input {NbTurns = 160});
     return s.GetScoreForDeliveryOn(turn);
 }
Пример #3
0
        public static Solution Solve(Input input)
        {
            _multidroneMalus = 1.0 + Helper.Rand.NextDouble(); //choose a random malus between 1 and 2 for this run

            var solution = new Solution(input);

            var drones = new Drone[input.NbDrones];
            for (int d = 0; d < input.NbDrones; d++)
            {
                drones[d] = new Drone(input, d);
            }

            var iteration = 0; //to ease debuging a particular step
            while (true)
            {
                iteration++;

                //chooseDrone furthest in the past
                Drone chosen = drones[0];
                for (int d = 1; d < drones.Length; d++)
                {
                    if (drones[d].turn < chosen.turn)
                        chosen = drones[d];
                }
                if (chosen.turn > input.NbTurns)
                {
                    Console.WriteLine("end of times reached");
                    return solution; //can't do shit anymore
                }

                //choose order
                WareHouse wh;
                var order = GetBestOrder(chosen, input, out wh);
                if (order == null)
                {
                    return solution; //no more order to deliver
                }

                if (wh != null)
                {
                    //go to warehouse and load everything
                    for (int i = 0; i < order.ItemsWanted.Length; i++)
                    {
                        var itemType = order.ItemsWanted[i];
                        if(itemType < 0)
                            continue;

                        wh.Stock[itemType]--;
                        Helper.Assert(() => wh.Stock[itemType] >= 0);
                        chosen.Load(wh, itemType);
                        solution.LoadForDelivery(chosen, wh, order, itemType);
                    }
                    //everything is loaded
                    for (int dd = 0; dd < order.NbItemsRemaining; dd++)
                    {
                        chosen.Deliver(order);
                    }
                    solution.DoDeliver(chosen, order, orderComplete: true);
                    order.ItemsWanted = null;
                }
                else //we'll have to go to several warehouses to load stuff OR we'll need several drones
                {
                    var loadedToDeliver = new List<int>();
                    var itemsToDeliver = (int[]) order.ItemsWanted.Clone();
                    while(itemsToDeliver.Any(it => it >= 0))
                    {
                        //best warehouse with item in stock
                        double bestScore = Double.PositiveInfinity;
                        WareHouse bestwh = null;
                        List<int> availableItems = null;
                        for (int w = 0; w < input.NbWareHouses; w++)
                        {
                            var currentwh = input.WareHouses[w];
                            var items = currentwh.GetFulfillable(itemsToDeliver);
                            if (items.Count > 0)
                            {
                                var score = (double) Helper.Distance(chosen.X, chosen.Y, currentwh.X, currentwh.Y)/items.Count; //time per item
                                if (score < bestScore)
                                {
                                    bestScore = score;
                                    bestwh = currentwh;
                                    availableItems = items;
                                }
                            }
                        }
                        wh = bestwh;

                        for (int i = 0; i < availableItems.Count; i++)
                        {
                            var itemType = order.ItemsWanted[availableItems[i]];
                            if (itemType < 0) //already delivered
                                continue;

                            if (!chosen.CheckLoad(wh, itemType))
                            {
                                //drone passed end of turns or is full
                                goto deliver; //maybe we could stash one or two more small items, but whatever
                            }
                            wh.Stock[itemType]--;
                            itemsToDeliver[availableItems[i]] = -1;
                            chosen.Load(wh, itemType);
                            solution.LoadForDelivery(chosen, wh, order, itemType);
                            loadedToDeliver.Add(availableItems[i]);
                        }
                    }
                deliver:
                    for (int dd = 0; dd < loadedToDeliver.Count; dd++)
                    {
                        chosen.Deliver(order);
                    }
                    for (int i = 0; i < loadedToDeliver.Count; i++)
                    {
                        Helper.Assert(() => order.ItemsWanted[loadedToDeliver[i]] >= 0);

                        order.TotalWeight -= input.ProductTypes[order.ItemsWanted[loadedToDeliver[i]]];
                        order.ItemsWanted[loadedToDeliver[i]] = -1; //mark as delivered
                        order.NbItemsRemaining--;
                    }
                    var orderComplete = order.NbItemsRemaining == 0;
                    if (orderComplete)
                    {
                        Helper.Assert(() => order.ItemsWanted.All(it => it < 0));
                        order.ItemsWanted = null;
                    }
                    else
                    {
                        Helper.Assert(() => order.ItemsWanted.Any(it => it >= 0));
                    }
                    solution.DoDeliver(chosen, order, orderComplete);
                }
            }
        }