using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace LD_24.Code { public static class TaskUtils { /// /// Finds the best possible pizzeria for the given map for the friends to meet up /// /// Target map /// Best pizzeria result object public static BestPizzeriaResult FindBestPizzeria(Map map) { int lowestCost = int.MaxValue; Point bestMeetingSpot = null; Point bestPizzeria = null; List friends = map.FindAll(MapTile.Friend); List pizzerias = map.FindAll(MapTile.Pizzeria); List meetingSpots = map.FindAll(MapTile.MeetingSpot); foreach (var meetingSpot in meetingSpots) { foreach (var pizzeria in pizzerias) { int totalCost = 0; int toPizzeriaCostPerFriend = FindBestPath(map, meetingSpot, pizzeria); if (toPizzeriaCostPerFriend < 0) { break; } totalCost += toPizzeriaCostPerFriend * friends.Count; bool failed = false; foreach (var friend in friends) { int toMeetingCost = FindBestPath(map, friend, meetingSpot); if (toMeetingCost < 0) { failed = true; break; } totalCost += toMeetingCost; int toHomeCost = FindBestPath(map, pizzeria, friend); if (toHomeCost < 0) { failed = true; break; } totalCost += toHomeCost; } if (failed) { break; } if (totalCost < lowestCost) { lowestCost = totalCost; bestMeetingSpot = meetingSpot; bestPizzeria = pizzeria; } } } if (bestMeetingSpot != null) { return new BestPizzeriaResult(bestPizzeria, bestMeetingSpot, lowestCost); } else { return null; } } /// /// Finds the minimum distance between 2 points on map. /// Returns -1, if there is no path /// /// Target map /// From positions /// To position /// Minimum distance public static int FindBestPath(Map map, Point from, Point to) { return FindBestPath(map, from, to, new Stack()); } /// /// Finds the minimum distance between 2 points on map. /// Returns -1, if there is no path /// /// Target map /// From positions /// To position /// Minimum distance private static int FindBestPath(Map map, Point from, Point to, Stack exploredPoints) { if (from.Equals(to)) { return 0; } int minCost = -1; exploredPoints.Push(from); foreach (var neighbour in GetNeighbours(map, from.X, from.Y)) { if (!exploredPoints.Contains(neighbour)) { int cost = FindBestPath(map, neighbour, to, exploredPoints); if (cost >= 0) { if (minCost < 0) { minCost = cost + 1; } else { minCost = Math.Min(minCost, cost + 1); } } } } exploredPoints.Pop(); return minCost; } /// /// Returns walkable neighbours around a given point /// /// Target map /// Target x /// Target y /// private static IEnumerable GetNeighbours(Map map, int x, int y) { if (map.IsInBounds(x + 1, y) && map.Get(x + 1, y) != MapTile.Wall) { yield return new Point(x + 1, y); } if (map.IsInBounds(x, y + 1) && map.Get(x, y + 1) != MapTile.Wall) { yield return new Point(x, y + 1); } if (map.IsInBounds(x - 1, y) && map.Get(x - 1, y) != MapTile.Wall) { yield return new Point(x - 1, y); } if (map.IsInBounds(x, y - 1) && map.Get(x, y - 1) != MapTile.Wall) { yield return new Point(x, y - 1); } } } }