Algorithms practice:leetcode
In a given grid of 0s and 1s, we have some starting row and column sr, sc and a target row and column tr, tc. Return the length of the shortest path from sr, sc to tr, tc that walks along 1 values only.
Each location in the path, including the start and the end, must be a 1. Each subsequent location in the path must be 4-directionally adjacent to the previous location.
It is guaranteed that grid[sr][sc] = grid[tr][tc] = 1, and the starting and target positions are different.
If the task is impossible, return -1.
input:
grid = [[1, 1, 1, 1], [0, 0, 0, 1], [1, 1, 1, 1]]
sr = 0, sc = 0, tr = 2, tc = 0
output: 8
(The lines below represent this grid:)
1111
0001
1111
grid = [[1, 1, 1, 1], [0, 0, 0, 1], [1, 0, 1, 1]]
sr = 0, sc = 0, tr = 2, tc = 0
output: -1
(The lines below represent this grid:)
1111
0001
1011
[time limit] 5000ms
[input] array.array.integer grid
1 ≤ arr.length = arr[i].length ≤ 10
[input] integer sr
[input] integer sc
[input] integer tr
[input] integer tc
All sr, sc, tr, tc are valid locations in the grid, grid[sr][sc] = grid[tr][tc] = 1, and (sr, sc) != (tr, tc).
[output] integer
#import <iostream>
#import <vector>
#import <unordered_set>
#include
using namespace std;
int shortestCellPath(const vector<vector<int>>& grid, int sr, int sc, int tr, int tc)
{
// your code goes here
// use BFS algorithm
vector<vector<int>> visited(grid);// value =1 is not visited
visited[sr][sc]=0;
deque<vector<int>> q;
vector<int> source{sr,sc,0};
q.push_back(source);
int R=grid.size();
int C=grid[0].size();
while(!q.empty())
{
int size = q.size();
for(int i=0;i<size;i++)
{
vector<int> curNode= q.front();
q.pop_front();
if(curNode[0] == tr && curNode[1] == tc)
return curNode[2];
vector<pair<int,int>> nextNodes;
nextNodes.push_back(make_pair(curNode[0]-1,curNode[1]));//up
nextNodes.push_back(make_pair(curNode[0]+1,curNode[1]));//bottom
nextNodes.push_back(make_pair(curNode[0],curNode[1]-1));//left
nextNodes.push_back(make_pair(curNode[0],curNode[1]+1));//right
for(auto nextNode:nextNodes)
{
int r = nextNode.first;
int c = nextNode.second;
if(r>=0&&r<R && c>=0&&c<C && grid[r][c]==1 && visited[r][c]==1)
{
vector<int> nextvec{r,c,curNode[2]+1};
q.push_back(nextvec);
visited[r][c]=0;
}
}
}
}
return -1;
}
int main()
{
return 0;
}
Solution: Breadth-First Search
Finding a shortest path is typically done with a breadth first search. Here, nodes are locations on the grid with value 1, and two nodes are neighbors if they are 4-directionally adjacent.
The breadth first search algorithm is given a source in the graph, and it explores all nodes distance 0 from the source, then all nodes distance 1, then all nodes distance 2, and so on. The algorithm records the node’s distance when it visits, and that way we can determine the shortest path in the graph to some target node.
By visiting nodes in order from distance to the source, this ensures that if we find the target word, we found it at the least possible distance and thus the answer is correct.
#import <iostream>
#import <vector>
using namespace std;
bool findMinIndex(const vector<vector<int>>& dist, const vector<vector<int>>& selected, int& r, int& c)
{
int aimR, aimC;
int min = INT_MAX;
for (int i = 0; i < dist.size(); i++)
{
for (int j = 0; j < dist[i].size(); j++)
{
if (selected[i][j] > 0 && min > dist[i][j])
{
min = dist[i][j];
aimR = i; aimC = j;
}
}
}
if (min == INT_MAX)
{
return false;
}
if (aimR == r && aimC == c)
{
return false;
}
else
{
r = aimR;
c = aimC;
return true;
}
};
int shortestCellPath(const vector<vector<int>>& grid, int sr, int sc, int tr, int tc)
{
// your code goes here
int height = grid.size();
int width = grid[0].size();
vector<vector<int>> dist(height, vector<int>(width,INT_MAX )); // min path value
vector<vector<int>> selected(grid); // value >0 means position can be selected
int curRow = sr;
int curCol = sc;
dist[curRow][curCol] = 0;
selected[curRow][curCol] = 0;
for (int i = 0; i < width * height; i++)
{
cout << endl;
cout << "current: " << curRow << " , " << curCol << " cur dist: " << dist[curRow][curCol] << endl;
// up (curRow-1, curCol)
if (curRow - 1 >= 0 && curRow - 1 < height && selected[curRow - 1][curCol] > 0)
{
dist[curRow - 1][curCol] = dist[curRow][curCol] + 1;
cout <<"up next: " << curRow - 1<<" , " << curCol << " , " << dist[curRow - 1][curCol] << " cur dist: " << dist[curRow][curCol] << endl;
}
//left (curRow, curCol-1)
if (curCol - 1 >= 0 && curCol - 1 < width && selected[curRow][curCol - 1] > 0)
{
dist[curRow][curCol - 1] = dist[curRow][curCol] + 1;
cout << "left next: " << curRow << " , " << curCol - 1 << " , " << dist[curRow][curCol - 1] << " cur dist: " << dist[curRow][curCol] << endl;
}
//right (curRow, curCol+1)
if (curCol + 1 < width && selected[curRow][curCol + 1] > 0)
{
dist[curRow][curCol + 1] = dist[curRow][curCol] + 1;
cout << "right next: " << curRow << " , " << curCol + 1 << " , " <<dist[curRow][curCol + 1] << " cur dist: " << dist[curRow][curCol] << endl;
}
//below (curRow+1, curCol)
if (curRow + 1 < height && selected[curRow + 1][curCol] > 0)
{
dist[curRow + 1][curCol] = dist[curRow][curCol] + 1;
cout << "below next: " << curRow + 1 << " , " << curCol << " , " << dist[curRow + 1][curCol] << endl;
}
selected[curRow][curCol] = 0;
if (!findMinIndex(dist, selected, curRow, curCol))
{
return -1;
}
else
{
if (curRow == tr && curCol == tc)
{
return dist[curRow][curCol];
}
cout << "find min " << curRow << " , " << curCol << endl;
}
//cout << curRow << " , " << curCol << " , " << dist[curRow][curCol] << endl;
}
return dist[tr][tc]==INT_MAX?-1:dist[tr][tc];
}
int main()
{
return 0;
}