Пример #1
0
 /// <summary>
 /// adds the load command immediately to the commands queue,
 /// and stores the delivery command for later
 /// </summary>
 public void LoadForDelivery(Drone d, WareHouse wh, Order o, int item)
 {
     var load = String.Format("{0} L {1} {2} {3}", d.id, wh.id, item, 1);
     var deli = String.Format("{0} D {1} {2} {3}", d.id, o.id, item, 1);
     _validatedCommands.AppendLine(load);
     _deliveryOrders[d.id].AppendLine(deli);
 }
Пример #2
0
        /// <summary>
        /// executes the deliver commands stashed for this drone
        /// </summary>
        public void DoDeliver(Drone d, Order o, bool orderComplete)
        {
            if (d.turn > o.DeliveryTime)
                o.DeliveryTime = d.turn;

            _validatedCommands.Append(_deliveryOrders[d.id]);
            _deliveryOrders[d.id].Clear();
            if (orderComplete)
            {
                Score += GetScoreForDeliveryOn(o.DeliveryTime-1);
            }
        }
Пример #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);
                }
            }
        }
Пример #4
0
        private static Order GetBestOrder(Drone d, Input input, out WareHouse goThere)
        {
            goThere = null;

            int bestCost = Int32.MaxValue;
            Order best = null;
            foreach (var order in input.Orders)
            {
                if(order.ItemsWanted == null)
                    continue; //already delivered

                int cost = Int32.MaxValue;
                WareHouse bestWh = null;
                var totalWeight = order.TotalWeight;
                if (totalWeight < input.MaxPayload) //one drone can take care of this order
                {
                    var eligibleWareHouses = input.WareHouses.Where(wh => wh.CanFullfillOrder(order.ItemsWanted) == order.NbItemsRemaining);
                    if (eligibleWareHouses.Any()) //everything is in the same warehouse
                    {
                        foreach (var wh in eligibleWareHouses)
                        {
                            var dist = Helper.Distance(d.X, d.Y, wh.X, wh.Y) + Helper.Distance(wh.X, wh.Y, order.X, order.Y);
                            if (dist < cost)
                            {
                                cost = dist;
                                bestWh = wh;
                            }
                        }
                    }
                    else //one drone can do everything, but has to go to several warehouses
                    {
                        //simulate going to 3 different wh
                        int dist = 0;
                        var wh = input.WareHouses[Helper.Rand.Next(input.NbWareHouses)];
                        dist += Helper.Distance(d.X, d.Y, wh.X, wh.Y) * 3;
                        dist += Helper.Distance(order.X, order.Y, wh.X, wh.Y);
                        if (dist < cost)
                        {
                            cost = dist;
                        }
                    }
                }
                else //we'll need several drones to complete this order
                {
                    //simulate going to 3 different wh
                    int dist = 0;
                    var wh = input.WareHouses[Helper.Rand.Next(input.NbWareHouses)];
                    dist += Helper.Distance(d.X, d.Y, wh.X, wh.Y)*3;
                    dist += Helper.Distance(order.X, order.Y, wh.X, wh.Y);
                    dist = (int)(_multidroneMalus * dist * totalWeight/input.MaxPayload); //apply a malus for estimated nb of drones needed
                    if (dist < cost)
                    {
                        cost = dist;
                    }
                }

                if (cost < bestCost)
                {
                    bestCost = cost;
                    best = order;
                    goThere = bestWh;
                }
            }
            return best;
        }