LCP 56. 信物传送
欢迎各位勇者来到力扣城,本次试炼主题为「信物传送」。
本次试炼场地设有若干传送带,matrix[i][j]
表示第 i
行 j
列的传送带运作方向,"^","v","<",">"
这四种符号分别表示 上、下、左、右 四个方向。信物会随传送带的方向移动。勇者每一次施法操作,可临时变更一处传送带的方向,在物品经过后传送带恢复原方向。
{:width=300px}
通关信物初始位于坐标 start
处,勇者需要将其移动到坐标 end
处,请返回勇者施法操作的最少次数。
注意:
start
和 end
的格式均为 [i,j]
示例 1:
输入:
matrix = [">>v","v^<","<><"], start = [0,1], end = [2,0]
输出:
1
解释: 如上图所示 当信物移动到
[1,1]
时,勇者施法一次将[1,1]
的传送方向^
从变更为<
从而信物移动到[1,0]
,后续到达end
位置 因此勇者最少需要施法操作 1 次
示例 2:
输入:
matrix = [">>v",">>v","^<<"], start = [0,0], end = [1,1]
输出:
0
解释:勇者无需施法,信物将自动传送至
end
位置
示例 3:
输入:
matrix = [">^^>","<^v>","^v^<"], start = [0,0], end = [1,3]
输出:
3
提示:
matrix
中仅包含 '^'、'v'、'<'、'>'
0 < matrix.length <= 100
0 < matrix[i].length <= 100
0 <= start[0],end[0] < matrix.length
0 <= start[1],end[1] < matrix[i].length
原站题解
python3 解法, 执行用时: 84 ms, 内存消耗: 16.2 MB, 提交时间: 2023-10-25 10:33:33
d = {"^": (-1, 0),"v": (1, 0),"<": (0, -1),">": (0, 1)} class Solution: def conveyorBelt(self, matrix: List[str], start: List[int], end: List[int]) -> int: m, n = len(matrix), len(matrix[0]) q = deque([(0, start[0], start[1])]) book = [[1234567890123] * n for _ in range(m)] book[start[0]][start[1]] = 0 while q: t, x, y = q.popleft() if [x, y] == end: return t for dr, (dx, dy) in d.items(): nx, ny = x + dx, y + dy if not (0 <= nx < m and 0 <= ny < n): continue nt = t + int(dr != matrix[x][y]) if dr == matrix[x][y]: if book[nx][ny] <= t: continue book[nx][ny] = t q.appendleft((t, nx, ny)) else: if book[nx][ny] <= t + 1: continue book[nx][ny] = t + 1 q.append((t + 1, nx, ny))
java 解法, 执行用时: 15 ms, 内存消耗: 42.1 MB, 提交时间: 2023-10-25 10:31:26
class Solution { private int ans; private int[][] dis; private int[][] dir = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; public void spfa(int[] start, int[] end, int m, int n, char[][] map, int cnt){ Queue<int[]> q = new LinkedList<>(); q.offer(start); dis[start[0]][start[1]] = 0; while (!q.isEmpty()){ int[] cur = q.poll(); for (int i = 0; i < 4; ++i){ int x = cur[0] + dir[i][0], y = cur[1] + dir[i][1]; if (x >= 0 && x < m && y >= 0 && y < n){ int len = 1; if ((i == 0 && map[cur[0]][cur[1]] == '^') || (i == 1 && map[cur[0]][cur[1]] == 'v') || (i == 2 && map[cur[0]][cur[1]] == '<') || (i == 3 && map[cur[0]][cur[1]] == '>')){ len = 0; } if (dis[cur[0]][cur[1]] + len < dis[x][y]){ dis[x][y] = dis[cur[0]][cur[1]] + len; q.offer(new int[]{x, y}); } } } } } public int conveyorBelt(String[] matrix, int[] start, int[] end) { int m = matrix.length, n = matrix[0].length(); char[][] map = new char[m][n]; for (int i = 0; i < m; ++i){ map[i] = matrix[i].toCharArray(); } dis = new int[m][n]; for (int i = 0; i < m; ++i){ for (int j = 0; j < n; ++j){ dis[i][j] = 1000000; } } ans = Integer.MAX_VALUE; spfa(start, end, m, n, map, 0); return dis[end[0]][end[1]]; } }
cpp 解法, 执行用时: 8 ms, 内存消耗: 9.3 MB, 提交时间: 2023-10-25 10:30:53
class Solution { public: typedef pair<int, int> PII; int dist[110][110]; //需要更改传送带的次数。 bool st[110][110]; int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; //4个方向。上右下左。 char g[4] = {'^', '>', 'v', '<'}; int conveyorBelt(vector<string>& matrix, vector<int>& start, vector<int>& end) { int n = matrix.size(), m = matrix[0].size(); deque<PII> q; q.push_back({start[0], start[1]}); memset(dist, -1, sizeof dist); dist[start[0]][start[1]] = 0; while (q.size()) { auto t = q.front(); q.pop_front(); int x = t.first, y = t.second; //到终点,直接return if (x == end[0] && y == end[1]) return dist[x][y]; if (st[x][y]) continue; st[x][y] = true; //printf("x = %d, y = %d, dist = %d\n", x, y, dist[x][y]); for (int i = 0; i < 4; i ++ ) { int a = x + dx[i], b = y + dy[i]; if (a < 0 || a >= n || b < 0 || b >= m || st[a][b]) continue; if (g[i] == matrix[x][y]) //如果当前前进的方向 和传送带一个方向 加入队头 { q.push_front({a, b}); dist[a][b] = dist[x][y]; } else //前进方向和传送带不是一个方向,加入队尾。 { q.push_back({a, b}); //如果当前点被更新过, 则更新为最小值。 if (dist[a][b] != -1) dist[a][b] = min(dist[a][b], dist[x][y] + 1); else dist[a][b] = dist[x][y] + 1; } //cout << a << ' ' << b << ' ' << dist[a][b] << endl; } } return 0; } };