public MapSearchInfo(MapSearchInfo m) { positions = new Position[m.positions.Length]; m.positions.CopyTo(positions, 0); found = new SortedSet <char>(m.found); steps = m.steps; }
static string CreateStr(MapSearchInfo msi) { string ps = ""; foreach (Position p in msi.positions) { ps += p.x.ToString() + ',' + p.y.ToString() + ','; } return(string.Join("", msi.found) + ps); }
static int CollectAllKeys(Map m, List <Position> positions) { Dictionary <string, MapSearchInfo> infoSteps = new Dictionary <string, MapSearchInfo>(); MapSearchInfo msi0 = new MapSearchInfo(positions.ToArray(), new SortedSet <char>(), 0); infoSteps[CreateStr(msi0)] = msi0; int minSteps = int.MaxValue; while (infoSteps.Count > 0) { PrintInfoSteps(infoSteps); Dictionary <string, MapSearchInfo> nextInfoSteps = new Dictionary <string, MapSearchInfo>(); foreach (var v in infoSteps) { Dictionary <char, (int steps, int idx)> keyDists = FindDirectlyReachableKeyDistances(m, v.Value); if (keyDists.Count == 0) { if (v.Value.steps < minSteps) { minSteps = v.Value.steps; } } foreach (var kvp in keyDists) { MapSearchInfo nextMsi = new MapSearchInfo(v.Value); nextMsi.steps += kvp.Value.steps; FindInMap(m, kvp.Key, ref nextMsi.positions[kvp.Value.idx]); nextMsi.found.Add(kvp.Key); Position p = new Position(); char c2 = char.ToUpper(kvp.Key); if (FindInMap(m, c2, ref p)) { nextMsi.found.Add(c2); } string sid = CreateStr(nextMsi); if (!nextInfoSteps.ContainsKey(sid) || nextInfoSteps[sid].steps > nextMsi.steps) { nextInfoSteps[sid] = nextMsi; } } } infoSteps = nextInfoSteps; } Console.WriteLine(); return(minSteps); }
static Dictionary <char, (int, int)> FindDirectlyReachableKeyDistances(Map m, MapSearchInfo msi) { List <Position> toVisit = new List <Position>(msi.positions); Dictionary <Position, (int steps, int idx)> steps = new Dictionary <Position, (int, int)>(); for (int i = 0; i < msi.positions.Length; i++) { steps[msi.positions[i]] = (0, i); } List <Position> keyPos = new List <Position>(); while (toVisit.Count > 0) { List <Position> toVisitNext = new List <Position>(); foreach (Position p in toVisit) { foreach (Position d in directions) { Position nextPos = p + d; char c = m[nextPos]; if (c != '#') { if (c == '.' || c == '@' || msi.found.Contains(c) || char.IsLower(c)) { (int steps, int idx)s = (steps[p].steps + 1, steps[p].idx); if (!steps.ContainsKey(nextPos) || s.steps < steps[nextPos].steps) { steps[nextPos] = s; if (c == '.' || c == '@' || msi.found.Contains(c)) { toVisitNext.Add(nextPos); } else { keyPos.Add(nextPos); } } } } } } toVisit = toVisitNext; } Dictionary <char, (int, int)> foundChars = new Dictionary <char, (int, int)>(); foreach (Position p in keyPos) { foundChars[m[p]] = steps[p]; } return(foundChars); }