private List <int> GenerateSolutionByDijkstra()
    {
        // A path is generated connecting random cells from the bottom and the top row
        int startCell = rnd.Next(0, cellsPerLine);
        int endCell   = rnd.Next(0, cellsPerLine) + numberOfCells - cellsPerLine;

        int[] distances = new int[numberOfCells];
        for (int i = 0; i < distances.Count(); i++)
        {
            if (i == startCell)
            {
                distances[i] = 0;
            }
            else
            {
                distances[i] = int.MaxValue;
            }
        }

        List <int> visitedNodes = new List <int>();

        visitedNodes.Add(startCell);

        int[] predecessors = new int[numberOfCells];

        while (visitedNodes.Count() < numberOfCells)
        {
            int currNode = visitedNodes.Last();
            List <Tuple <int, int> > neighboursCosts = adjacencyList.GetAllNeighboursCost(currNode);
            foreach (Tuple <int, int> nc in neighboursCosts)
            {
                if (distances[currNode] + nc.Item2 < distances[nc.Item1])
                {
                    distances[nc.Item1]    = distances[currNode] + nc.Item2;
                    predecessors[nc.Item1] = currNode;
                }
            }

            int nextNode = Enumerable.Range(0, numberOfCells).Where(x => !visitedNodes.Contains(x)).OrderBy(x => distances[x]).First();
            visitedNodes.Add(nextNode);
        }

        List <int> shortestPath  = new List <int>();
        int        backtrackNode = endCell;

        while (backtrackNode != startCell)
        {
            shortestPath.Insert(0, backtrackNode);
            backtrackNode = predecessors[backtrackNode];
        }
        shortestPath.Insert(0, startCell);

        return(shortestPath);
    }