private int GetShortestDistanceToMineInOtherComponent(Edge edge, PunterConnectedComponents punterConnectedComponents, Punter punter) { return(Math.Min( GetShortestDistanceToMineInOtherComponent(edge.Source, punterConnectedComponents, punter), GetShortestDistanceToMineInOtherComponent(edge.Target, punterConnectedComponents, punter) )); }
private static void CheckComponents(Node[] component1, Node[] component2, PunterConnectedComponents actual, int punterId, bool expected) { foreach (var left in component1) { foreach (var right in component2) { actual.IsInSameComponent(left.Id, right.Id, punterId).Should().Be(expected, $"{left.Id} - {right.Id}, punter {punterId}"); } } }
private int GetShortestDistanceToMineInOtherComponent(Node node, PunterConnectedComponents punterConnectedComponents, Punter punter) { var minesInOtherComponents = scorer.State.Mines .Where(mine => !punterConnectedComponents.IsInSameComponent(mine.Id, node.Id, punter.Id)) .ToArray(); if (minesInOtherComponents.Length == 0) { return(1000 * 1000 * 1000); } return(minesInOtherComponents.Min(mine => scorer.GetDistance(mine, node))); }
private int GetWeight(Edge claimEdge, Punter punter, PunterConnectedComponents punterConnectedComponents) { if (punterConnectedComponents.IsInSameComponent(claimEdge.Source.Id, claimEdge.Target.Id, punter.Id)) { return(0); } claimEdge.Punter = punter; var leftComponent = punterConnectedComponents.GetComponent(punter.Id, claimEdge.Source.Id); var rightComponent = punterConnectedComponents.GetComponent(punter.Id, claimEdge.Target.Id); var scoreDelta = scorer.ScoreForUnitingComponents(leftComponent, rightComponent); claimEdge.Punter = null; return(scoreDelta); }
private int GetWeight(Edge claimEdge, Punter punter, PunterConnectedComponents punterConnectedComponents) { if (punterConnectedComponents.IsInSameComponent(claimEdge.Source.Id, claimEdge.Target.Id, punter.Id)) { return(0); } claimEdge.Punter = punter; var leftComponent = punterConnectedComponents.GetComponent(punter.Id, claimEdge.Source.Id); var rightComponent = punterConnectedComponents.GetComponent(punter.Id, claimEdge.Target.Id); var scalingFactor = Math.Max(10, maxScore / 100); var scoreDelta = (scorer.ScoreForUnitingComponents(leftComponent, rightComponent) + scalingFactor - 1) / scalingFactor; claimEdge.Punter = null; return(scoreDelta); }
private Edge GetBridge(GameState gameState, Map map, Punter punter, HashSet <int> reachableNodeIds, PunterConnectedComponents strictComponents, Edge[] bridgeEdges) { var goodBridges = bridgeEdges .Select(x => new { edge = x, weight = GetWeightForBridge(map, x, punter, reachableNodeIds) }) .Where(x => x.weight > 0) .ToArray(); bridgeMaxScore = goodBridges.Length > 0 ? goodBridges.Max(x => x.weight) : 1; maxScore = goodBridges.Length > 0 ? goodBridges.Max(x => GetWeight(x.edge, punter, strictComponents)) : 1; var bestBridge = goodBridges .Select(x => x.edge) .OrderByDescending(x => GetWeightForBridge(map, x, punter, reachableNodeIds)) .ThenByDescending(x => GetWeight(x, punter, strictComponents)) .ThenBy(x => GetShortestDistanceToMineInOtherComponent(x, strictComponents, punter)) .ThenByDescending(x => CountFreeNeighborEdges(gameState, x)) .FirstOrDefault(); return(bestBridge); }
private static PunterConnectedComponents GetConnectedComponents(Map map, bool withFreeEdges) { var connectedComponents = new PunterConnectedComponents(); var punters = map .Edges .Select(x => x.Punter) .Where(x => x != null) .Select(x => x.Id) .Distinct() .Select(x => new Punter { Id = x }) .ToArray(); var queue = new Queue <Node>(); foreach (var punter in punters) { var visitedNodeIds = new HashSet <int>(); foreach (var node in map.Nodes) { if (visitedNodeIds.Contains(node.Id)) { continue; } var component = new List <Node>(); component.Add(AddNode(queue, visitedNodeIds, node)); Bfs(map, punter, queue, visitedNodeIds, component, withFreeEdges); var nodeIds = component.Select(x => x.Id).ToArray(); connectedComponents.AddComponent(nodeIds, punter.Id); } } return(connectedComponents); }