public static ProblemDescription LoadFromFile(string path) { var description = new ProblemDescription(); using (var reader = File.OpenText(path)) { var parametersLine = reader.ReadLine(); var parameters = parametersLine.Split(' '); description.NumRows = int.Parse(parameters[0]); description.NumCols = int.Parse(parameters[1]); description.NumDrones = int.Parse(parameters[2]); description.Deadline = int.Parse(parameters[3]); description.MaximumLoad = int.Parse(parameters[4]); var numProducts = int.Parse(reader.ReadLine()); description.ProductWeights = reader.ReadLine() .Split(' ') .Select(int.Parse) .ToList(); int numWarehouses = int.Parse(reader.ReadLine()); for (int i = 0; i < numWarehouses; ++i) { var locationLine = reader.ReadLine(); var location = locationLine.Split(' '); var warehouse = new Warehouse(); warehouse.position = new Position(int.Parse(location[0]), int.Parse(location[1])); warehouse.heldProducts = reader.ReadLine() .Split(' ') .Select(int.Parse) .ToList(); description.Warehouses.Add(warehouse); } int numOrders = int.Parse(reader.ReadLine()); int orderId = 0; for (int i = 0; i < numOrders; ++i) { var locationLine = reader.ReadLine(); var location = locationLine.Split(' '); var order = new Order(); order.RealId = orderId++; order.position = new Position(int.Parse(location[0]), int.Parse(location[1])); int numProductTypes = int.Parse(reader.ReadLine()); var orderInfoLine = reader.ReadLine(); var orderInfoItems = orderInfoLine.Split(' '); for (int j = 0; j < numProductTypes; ++j) { var productType = int.Parse(orderInfoItems[j]); if (order.orderedProducts.ContainsKey(productType)) { order.orderedProducts[productType]++; } else { order.orderedProducts[productType] = 1; } } BreakAndAddOrder(description, order); } } return description; }
private static void BreakAndAddOrder(ProblemDescription description, Order order) { int maxPayload = description.MaximumLoad; while (GetOrderLoad(description, order) > maxPayload) { var newOrder = new Order(); newOrder.RealId = order.RealId; newOrder.position = order.position; int newLoad = 0; for (;;) { int heaviestItemSoFar = -1; int bestWeight = int.MinValue; foreach (var item in order.orderedProducts) { if (item.Value == 0) continue; int weight = description.ProductWeights[item.Key]; if (newLoad + weight < maxPayload && weight > bestWeight) { heaviestItemSoFar = item.Key; bestWeight = weight; } } if (heaviestItemSoFar < 0) { break; } int numItems = (maxPayload - newLoad) / bestWeight; numItems = Math.Min(numItems, order.orderedProducts[heaviestItemSoFar]); order.orderedProducts[heaviestItemSoFar] -= numItems; newOrder.orderedProducts[heaviestItemSoFar] = numItems; newLoad += numItems * bestWeight; } description.Orders.Add(newOrder); } description.Orders.Add(order); }
private static int GetOrderLoad(ProblemDescription description, Order order) { int total = 0; foreach (var item in order.orderedProducts) { var type = item.Key; var quantity = item.Value; total += description.ProductWeights[type] * quantity; } return total; }
private List<int> FindBestPath(Order order, ProblemDescription description) { List<int> warehouseList = new List<int>(); // FIXME: Do this better. // We may be able to find a single warehouse with everything. // So maybe try multiple alternatives Dictionary<int, int> missingItems = new Dictionary<int, int>(order.orderedProducts); List<Tuple<Warehouse, int>> warehouses = description.Warehouses .Select((warehouse, warehouseId) => Tuple.Create(warehouse, warehouseId)) .ToList(); var activePosition = NextPosition; for (;;) { int maxValue = int.MaxValue; int minIndex = -1; for (int i = 0; i < warehouses.Count; ++i) { var warehouse = warehouses[i]; var distance = DistanceCalculator.CalculateSquareDistance(activePosition, warehouse.Item1.position); if (distance < maxValue) { maxValue = distance; minIndex = i; } } var tuple = warehouses[minIndex]; var heldProducts = tuple.Item1.heldProducts; bool anyMatch = false; foreach (var itemType in missingItems.Keys.ToList()) { if (missingItems[itemType] == 0) { continue; } if (itemType < heldProducts.Count && heldProducts[itemType] > 0) { var numProducts = Math.Min(heldProducts[itemType], missingItems[itemType]); anyMatch = true; missingItems[itemType] -= numProducts; if (missingItems[itemType] == 0) { missingItems.Remove(itemType); } } } if (anyMatch) { warehouseList.Add(tuple.Item2); warehouses.Remove(tuple); activePosition = tuple.Item1.position; break; } if (missingItems.Count == 0) { break; } return null; } return warehouseList; }