/// <summary> /// To solve this since we can start from any cell on the left axis and we can end at any cell on the right axis /// Lets define a source cell which has edges which connect to all the cells on the left axis ie mat[i,0] /// Also define a destination cell which has all edges connected to all the cells on the right axis ie mat[i,mat.Length-1] /// /// Then we can do a djkstra's shortest path algorithm to figure out the shortest path. /// The running time of this algo is O(V+E) in worse case E = O(V^2) /// </summary> /// <param name="mat"></param> /// <returns></returns> public List <Cell> GetPath(int[,] mat) { UndirectedGraphWithVertexDictionary udg = new UndirectedGraphWithVertexDictionary(); // Fix the source and destination cells. GraphVertexWithDistance source = new GraphVertexWithDistance(new Cell(-1, -1)); GraphVertexWithDistance destination = new GraphVertexWithDistance(new Cell(mat.Length, mat.Length)); // Create the graph vertices and put it in a matrix GraphVertexWithDistance[,] allVertex = CreateGraphFromMatrix(mat, source, destination); // Now we need to do dijkstras shortest path algorithm. Each edge will have a weight of 1. return(DijkstrasShortestPath(source, destination, allVertex)); }
/// <summary> /// Create graph from the matrix and add all the edges in the format shown below /// |------*---*-------*| /// |--*---*-------*----| /// |--*------*--------*| ///s ---|------*-----*--*---| --- d /// |---*-------*----*--| /// |---*---*----------*| /// |-----*---*-------*-| /// |---*----------*---*| /// </summary> /// <param name="mat"></param> /// <param name="source"></param> /// <param name="destination"></param> /// <returns></returns> private GraphVertexWithDistance[,] CreateGraphFromMatrix(int[,] mat, GraphVertexWithDistance source, GraphVertexWithDistance destination) { // Create the graph from the matrix GraphVertexWithDistance[,] allVertex = new GraphVertexWithDistance[mat.GetLength(0), mat.GetLength(1)]; for (int i = 0; i < mat.GetLength(0); i++) { for (int j = 0; j < mat.GetLength(1); j++) { allVertex[i, j] = new GraphVertexWithDistance(new Cell(i, j)); } } // Add all the edges to the graph vertices for (int i = 0; i < mat.GetLength(0); i++) { for (int j = 0; j < mat.GetLength(1); j++) { if (j == 0 && mat[i, j] != 1) { // This is the left side of the matrix source.AddEdge(allVertex[i, j]); allVertex[i, j].AddEdge(source); } if (j == mat.GetLength(1) - 1 && mat[i, j] != 1) { // This is the right side of the matrix destination.AddEdge(allVertex[i, j]); allVertex[i, j].AddEdge(destination); } if (j + 1 < mat.GetLength(1) && mat[i, j + 1] != 1 && mat[i, j] != 1) { // Add the edge to the right of the graphvertex allVertex[i,j] allVertex[i, j].AddEdge(allVertex[i, j + 1]); allVertex[i, j + 1].AddEdge(allVertex[i, j]); } if (i + 1 < mat.GetLength(0) && mat[i + 1, j] != 1 && mat[i, j] != 1) { // Add the edge below graphVertex allVertex[i,j] allVertex[i, j].AddEdge(allVertex[i + 1, j]); allVertex[i + 1, j].AddEdge(allVertex[i, j]); } } } return(allVertex); }
public GraphEdge(GraphVertexWithDistance source, GraphVertexWithDistance destination) { Source = source; Destination = destination; Distance = 1; }
public void AddEdge(GraphVertexWithDistance neighbour) { NeighbourEdges.Add(new GraphEdge(this, neighbour)); }
private List <Cell> DijkstrasShortestPath(GraphVertexWithDistance source, GraphVertexWithDistance destination, GraphVertexWithDistance[,] allVertex) { // Initialization MinHeap <GraphVertexWithDistance> mh = new MinHeap <GraphVertexWithDistance>(allVertex.GetLength(0) * allVertex.GetLength(1) + 2); Dictionary <GraphVertexWithDistance, GraphVertexWithDistance> backtrack = new Dictionary <GraphVertexWithDistance, GraphVertexWithDistance>(); Dictionary <GraphVertexWithDistance, int> FinalDistance = new Dictionary <GraphVertexWithDistance, int>(); // Add all the graphvertices to the minheap source.Distance = 0; mh.Insert(source); mh.Insert(destination); for (int i = 0; i < allVertex.GetLength(0); i++) { for (int j = 0; j < allVertex.GetLength(1); j++) { mh.Insert(allVertex[i, j]); } } while (mh.HeapSize > 0) { GraphVertexWithDistance vertex = mh.ExtractMin(); FinalDistance[vertex] = vertex.Distance; if (vertex == destination) { // We have reached the destination. No need to calculate final distance for all the other graph vertex break; } foreach (GraphEdge neighbourEdge in vertex.NeighbourEdges) { if (!FinalDistance.ContainsKey(neighbourEdge.Destination)) { if (vertex.Distance + 1 < neighbourEdge.Destination.Distance) { GraphVertexWithDistance oldVertex = neighbourEdge.Destination; neighbourEdge.Destination.Distance = vertex.Distance + 1; GraphVertexWithDistance newVertex = neighbourEdge.Destination; mh.Replace(newVertex, oldVertex); backtrack[neighbourEdge.Destination] = vertex; } } } } // Back track to get the path List <Cell> path = new List <Cell>(); GraphVertexWithDistance currentVertex = destination; while (currentVertex != source) { if (backtrack.ContainsKey(currentVertex)) { if (currentVertex != destination) { path.Add(currentVertex.Id); } currentVertex = backtrack[currentVertex]; } else { break; } } path.Reverse(); return(path); }