分值:200
题目描述
有一辆汽车需要从m * n的地图的左上角(起点)开往地图的右下角(终点),去往每一个地区都需要消耗一定的油量,加油站可进行加油。
请你计算汽车确保从起点到达终点时所需的最少初始油量说明:
(1) 智能汽车可以上下左右四个方向移动1。
(2) 地图上的数字取值是0或-1或者正整数:
-1:表示加油站,可以加满油,汽车的油箱容量最大为100;0:表示这个地区是障碍物,汽车不能通过。- 正整数:表示汽车走过这个地区的耗油量。
(3) 如果汽车无论如何都无法到达终点,则返回-1。
输入描述:
第一行为两个数字,M,N,表示地图的大小为M,N。
后面一个M * N的矩阵,其中的值是0或-1或正整数。
输出描述:
如果汽车无论如何都无法到达终点,则返回-1。
如果汽车可以到达终点,则返回最少的初始油量。
示例1
输入:
2 2
10 20
30 40
输出:
70
解释:
路线为 (0, 0) -> (0, 1) -> (1, 1), 销毁油量为 10 + 20 + 40 = 70
示例2
输入:
4 4
10 30 30 20
30 30 20 10
10 20 10 40
10 20 30 40
输出:
-1
解释:
油箱加满的油量为 100,中途没有加油站,所以无论如何也达到不了终点。
Tips:
0< M, N < 200- 加油站的总数不超过
200个 - (0, 0) 位置为正整数
思路
- 注意到到达加油站之后可以加满油,也就是说到达加油站之后,后面的路程就跟初始油量无关了。
- 那么可以在每一次达到一个加油站之后,判断此加油站是否可以达到终点。然后挑选可以达到的加油站职中需要的最小油量的加油站即可。
- 优先队列可以快速帮助拿到下一个需要最小油量的位置。这样可以保证在多种方案到达此位置时,第一次的方案就是最优的。
- 如果想把优先队列从最大堆变成最小堆(反之亦然),可以不重新写个比较器,直接将数值取相反数(比如
value为k那么存进去时选择存-k即可,记得取出来时重新取个相反数)。
复杂度分析
- 时间复杂度: O(K∗M∗N)O(K*M*N)O(K∗M∗N),其中
K为加油站数量(最多为200),M,N,表示地图的大小为M,N - 空间复杂度: O(M∗N)O(M*N)O(M∗N),其中
M,N,表示地图的大小为M,N
AC 代码
C++ 版
#include <bits/stdc++.h>
using namespace std;
bool check(vector<vector<int>> &matrix, int idxX, int idxY)
{
priority_queue<pair<int, pair<int, int>>> q;
int dis[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, n = matrix.size(), m = matrix[0].size();
vector<vector<bool>> vis(n, vector<bool>(m, 0));
q.push({100, {idxX, idxY}});
vis[idxX][idxY] = 1;
while (!q.empty())
{
int lastGas = q.top().first;
int x = q.top().second.first;
int y = q.top().second.second;
if (x == n - 1 && y == m - 1)
{
return true;
}
q.pop();
for (int i = 0; i < 4; i++)
{
int nx = x + dis[i][0];
int ny = y + dis[i][1];
if (nx >= 0 && nx < n && ny >= 0 && ny < m && !vis[nx][ny])
{
vis[nx][ny] = 1;
if (matrix[nx][ny] == 0)
{
continue;
}
else if (matrix[nx][ny] > 0 && matrix[nx][ny] <= lastGas)
{
// 到下一站要减去消耗的汽油
q.push({lastGas - matrix[nx][ny], {nx, ny}});
}
else if (matrix[nx][ny] == -1)
{
// 重新补充汽油
q.push({100, {nx, ny}});
}
}
}
}
return false;
}
int main()
{
int n, m, ans = -1, dis[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
cin >> n >> m;
vector<vector<int>> matrix(n, vector<int>(m)), vis(n, vector<int>(m, 0));
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
cin >> matrix[i][j];
}
}
// 默认大根堆, 变成小根堆的话要取相反数或者重新写个比较器
priority_queue<pair<int, pair<int, int>>> q;
q.push({-matrix[0][0], {0, 0}});
vis[0][0] = 1;
while (!q.empty())
{
int cost = -q.top().first; // 这里记得取相反数拿到的才是原本的值
int x = q.top().second.first;
int y = q.top().second.second;
q.pop();
if (x == n - 1 && y == m - 1 && cost <= 100)
{
ans = cost;
break;
}
else
{
for (int i = 0; i < 4; i++)
{
int nx = x + dis[i][0];
int ny = y + dis[i][1];
if (nx >= 0 && nx < n && ny >= 0 && ny < m && !vis[nx][ny])
{
vis[nx][ny] = 1;
if (matrix[nx][ny] == 0)
{
continue;
}
else if (matrix[nx][ny] > 0 && cost + matrix[nx][ny] <= 100)
{
q.push({-(cost + matrix[nx][ny]), {nx, ny}});
}
else if (matrix[nx][ny] == -1 && check(matrix, nx, ny))
{
cout << cost << endl;
return 0;
}
}
}
}
}
cout << ans << endl;
return 0;
}
JAVA 版
import java.util.*;
public class Main {
public static boolean check(int[][] matrix, int idxX, int idxY) {
int[][] dis = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int n = matrix.length;
int m = matrix[0].length;
boolean[][] vis = new boolean[n][m];
PriorityQueue<int[]> q = new PriorityQueue<>((a, b) -> b[0] - a[0]);
q.offer(new int[]{100, idxX, idxY});
vis[idxX][idxY] = true;
while (!q.isEmpty()) {
int lastGas = q.peek()[0];
int x = q.peek()[1];
int y = q.peek()[2];
q.poll();
if (x == n - 1 && y == m - 1) {
return true;
}
for (int i = 0; i < 4; i++) {
int nx = x + dis[i][0];
int ny = y + dis[i][1];
if (nx >= 0 && nx < n && ny >= 0 && ny < m && !vis[nx][ny]) {
vis[nx][ny] = true;
if (matrix[nx][ny] == 0) {
continue;
} else if (matrix[nx][ny] > 0 && matrix[nx][ny] <= lastGas) {
q.offer(new int[]{lastGas - matrix[nx][ny], nx, ny});
} else if (matrix[nx][ny] == -1) {
q.offer(new int[]{100, nx, ny});
}
}
}
}
return false;
}
public static int minInitialFuel(int[][] matrix) {
int[][] dis = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int n = matrix.length;
int m = matrix[0].length;
boolean[][] vis = new boolean[n][m];
PriorityQueue<int[]> q = new PriorityQueue<>((a, b) -> b[0] - a[0]);
q.offer(new int[]{-matrix[0][0], 0, 0});
vis[0][0] = true;
while (!q.isEmpty()) {
int cost = -q.peek()[0];
int x = q.peek()[1];
int y = q.peek()[2];
q.poll();
if (x == n - 1 && y == m - 1 && cost <= 100) {
return cost;
} else {
for (int i = 0; i < 4; i++) {
int nx = x + dis[i][0];
int ny = y + dis[i][1];
if (nx >= 0 && nx < n && ny >= 0 && ny < m && !vis[nx][ny]) {
vis[nx][ny] = true;
if (matrix[nx][ny] == 0) {
continue;
} else if (matrix[nx][ny] > 0 && cost + matrix[nx][ny] <= 100) {
q.offer(new int[]{- (cost + matrix[nx][ny]), nx, ny});
} else if (matrix[nx][ny] == -1 && check(matrix, nx, ny)) {
return cost;
}
}
}
}
}
return -1;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
int[][] matrix = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
matrix[i][j] = scanner.nextInt();
}
}
int result = minInitialFuel(matrix);
System.out.println(result);
}
}
Python 版
import heapq
def check(matrix, idxX, idxY):
q = [(-100, (idxX, idxY))]
n, m = len(matrix), len(matrix[0])
vis = [[False for _ in range(m)] for _ in range(n)]
vis[idxX][idxY] = True
dis = [(1, 0), (-1, 0), (0, 1), (0, -1)]
while q:
lastGas, (x, y) = heapq.heappop(q)
lastGas *= -1
if x == n - 1 and y == m - 1:
return True
for dx, dy in dis:
nx, ny = x + dx, y + dy
if 0 <= nx < n and 0 <= ny < m and not vis[nx][ny]:
vis[nx][ny] = True
if matrix[nx][ny] == 0:
continue
elif 0 < matrix[nx][ny] <= lastGas:
heapq.heappush(q, (-(lastGas - matrix[nx][ny]), (nx, ny)))
elif matrix[nx][ny] == -1:
heapq.heappush(q, (-100, (nx, ny)))
return False
def main():
n, m = map(int, input().split())
matrix = [list(map(int, input().split())) for _ in range(n)]
vis = [[0 for _ in range(m)] for _ in range(n)]
dis = [(1, 0), (-1, 0), (0, 1), (0, -1)]
q = [(matrix[0][0], (0, 0))]
vis[0][0] = 1
while q:
cost, (x, y) = heapq.heappop(q)
cost = cost
if x == n - 1 and y == m - 1 and cost <= 100:
print(cost)
return
for dx, dy in dis:
nx, ny = x + dx, y + dy
if 0 <= nx < n and 0 <= ny < m and not vis[nx][ny]:
vis[nx][ny] = 1
if matrix[nx][ny] == 0:
continue
elif 0 < matrix[nx][ny] <= cost + matrix[nx][ny] <= 100:
heapq.heappush(q, (cost + matrix[nx][ny], (nx, ny)))
elif matrix[nx][ny] == -1 and check(matrix, nx, ny):
print(cost)
return
print(-1)
if __name__ == "__main__":
main()
1197

被折叠的 条评论
为什么被折叠?



