/// <summary> /// Wersja III i IV zadania /// Zwraca najkrótszy możliwy czas przejścia przez labirynt z użyciem co najwyżej k lasek dynamitu /// </summary> /// <param name="maze">labirynt</param> /// <param name="k">liczba dostępnych lasek dynamitu, dla wersji III k=1</param> /// <param name="path">zwracana ścieżka</param> /// <param name="t">czas zburzenia ściany</param> /// // pomysl: k+1 takich samych grafow(warstw) bez krawedzi X , a krawedzie X to takie "mosty" miedzy warstwami // ETAP 3 i 4 public int FindShortestPathWithKDynamites(char[,] maze, int k, out string path, int t) { path = ""; int X = maze.GetLength(1); int Y = maze.GetLength(0); int n = X * Y; // liczba punktow w tablicy, dla ulatwienia w szukaniu numeru wierzcholka w innej warstwie grafu int start = -1; int end = -1; AdjacencyListsGraph <AVLAdjacencyList> g = new AdjacencyListsGraph <AVLAdjacencyList>(true, (k + 1) * n); PathsInfo[] p = null; createGraph(maze, g, t, out start, out end, k, n); ShortestPathsGraphExtender.DijkstraShortestPaths(g, start, out p); int[] dist = new int[k + 1]; // tablica najlepszych drog dla uzycia dynamitow od 0 do k for (int i = 0; i <= k; ++i) { dist[i] = -1; } int min = int.MaxValue; int index = 0; // ilosc dynamitow zuzytych dla najlepszej drogi for (int i = 0; i <= k; ++i) // sprawdzenie dla kazdej ilosci uzytego dynamitu najlepszej drogi { int tmp = (int)p[end + i * n].Dist; if (!Double.IsNaN(p[end + i * n].Dist)) // jesli nie NaN to porownac z wartoscia najmniejsza { dist[i] = tmp; if (tmp < min) // jesli nowa wartosc lepsza to zapisac jako min { min = tmp; index = i; } } } if (min == int.MaxValue) { return(-1); // jesli nie znaleziono sciezki to -1 } else { if (X > 1) { path = constructStringE34(PathsInfo.ConstructPath(start, end + index * n, p), X, n); } else // jesli kolejne wierzcholki grafu nie sa na tablicy po prawo/lewo, tylko gora/dol (bo wymiar 1xN czy Nx1 nie wiem) { path = constructStringE341xN(PathsInfo.ConstructPath(start, end + index * n, p), X, n); } return(min); } }
// ETAP 1 i 2 public int FindShortestPath(char[,] maze, bool withDynamite, out string path, int t = 0) { path = ""; int X = maze.GetLength(1); int Y = maze.GetLength(0); int start = -1; int end = -1; AdjacencyListsGraph <AVLAdjacencyList> g = new AdjacencyListsGraph <AVLAdjacencyList>(true, X * Y); PathsInfo[] p = null; if (t == 0) { createGraph(maze, g, out start, out end); } else { createGraph(maze, g, t, out start, out end); } ShortestPathsGraphExtender.DijkstraShortestPaths(g, start, out p); int dist = (int)p[end].Dist; if (!Double.IsNaN(p[end].Dist)) { if (X > 1) { path = constructString(PathsInfo.ConstructPath(start, end, p)); } else { path = constructString1xN(PathsInfo.ConstructPath(start, end, p)); } return(dist); } else { return(-1); } }
/// <summary> /// Sprawdza możliwość przejazdu między dzielnicami-wielokątami district1 i district2, /// tzn. istnieją para ulic, pomiędzy którymi jest przejazd /// oraz fragment jednej ulicy należy do obszaru jednej z dzielnic i fragment drugiej należy do obszaru drugiej dzielnicy /// </summary> /// <returns>Informacja czy istnieje przejazd między dzielnicami</returns> // etap 4 public bool CheckDistricts(Street[] streets, Point[] district1, Point[] district2, out List <int> path, out List <Point> intersections) { path = new List <int>(); intersections = new List <Point>(); int S = streets.Length; int n1 = district1.Length; int n2 = district2.Length; Graph g = new AdjacencyListsGraph <SimpleAdjacencyList>(false, S + 2); // 0..S-1 streets S == district1, S + 1 == district2 for (int i = 0; i < S; ++i) { // ulica wchodzi do district1 for (int k = 0; k < n1; ++k) { if (CheckIntersection(streets[i], new Street(district1[k % n1], district1[(k + 1) % n1])) != 0) { g.AddEdge(i, S); } } // ulica wchodzi do district2 for (int k = 0; k < n2; ++k) { if (CheckIntersection(streets[i], new Street(district2[k % n2], district2[(k + 1) % n2])) != 0) { g.AddEdge(i, S + 1); } } // ulica krzyzuje sie z kolejna ulica if (i != S - 1) { for (int j = i + 1; j < S; ++j) { if (CheckIntersection(streets[i], streets[j]) != 0) { g.AddEdge(i, j); } } } } PathsInfo[] p = new PathsInfo[S + 2]; ShortestPathsGraphExtender.DijkstraShortestPaths(g, S, out p); Edge[] e = PathsInfo.ConstructPath(S, S + 1, p); // jesli istnieje sciezka od S do S+1 if (!Double.IsNaN(p[S + 1].Dist)) { path = new List <int>(); // pododawac kolejne pkty (bez S i bez S+1) for (int j = 0; j < e.Length - 1; ++j) { path.Add(e[j].To); } intersections = new List <Point>(); // przeciecia kolejnych ulic for (int j = 0; j < path.Count - 1; ++j) { intersections.Add(GetIntersectionPoint(streets[path[j]], streets[path[j + 1]])); } return(true); } else { return(false); } }