题目描述
有一辆汽车需要从m*n的地图的左上角(起点)开往地图的右下角(终点),去往每一个地区都需要消耗一定的油量,加油站可进行加油
请你计算汽车确保从起点到达终点时所需的最少初始油量说明:
(1)智能汽车可以上、下、左、右四个方向移动(2)地图中的数字取值是0或-1或正整数:
-1:表示加油站,可以加满油,汽车的油箱容量最大为100;0:表示这个地区是障碍物,汽车不能通过;正整数:表示汽车走过这个地区的耗油量
(3)如果汽车无论如何都无法到达终点,则返回-1
输入描述
第一行为两个数字,M、N,表示地图的大小为M*N
后面是一个M*N的矩阵,其中的值是0或-1或正整数,加油站的总数不超过200个
输出描述
如果汽车无论如何都无法到达终点,则返回-1。如果汽车可以到达终点,则返回最少的初始油量。
补充说明
0<M,N<=200
示例1
输入
2,2
10,20
30,40
输出
70
说明
行走路线为:右->下
示例2
输入
4,4
10,30,30,20
30,30,-1,10
0,20,20,40
10,-1,30,40
输出
70
说明
行走路线为:右->右->下->下->下->右
示例3
输入
4,5
10,0,30,-1,10
30,0,20,0,20
10,0,10,0,30
10,-1,30,0,10
输出
60
说明
行走路线为:下->下->下->右->右->上->上->上->右->右->下->下->下
示例4
输入
4,4
10,30,30,20
30,30,20,10
10,20,10,40
10,20,30,40
输出
-1
说明
无论如何都无法到达终点
Java
import java.util.PriorityQueue;
import java.util.Scanner;
public class Main {
// 定义一个极大值用来表示无限大
public static int inf = (int) 1e9;
// 地图的行数和列数
public static int n, m;
// 地图数组
public static int[][] g;
// 表示四个方向的移动
public static int[][] nxt = new int[][] { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
// 表示是否已经访问过的位置
public static Boolean[][][] f;
// 优先队列用于广度优先搜索
public static PriorityQueue<int[]> pq;
// 检查给定的初始油量mid是否能达到终点
public static boolean check(int mid) {
// 如果起点的油耗量大于初始油量,则返回false
if (g[0][0] > mid) {
return false;
}
// 优先队列用于存储当前路径的油耗情况
pq = new PriorityQueue<>((x, y) -> {
return x[0] - y[0];
});
// 初始化访问数组,用于记录在特定油量下,某位置是否被访问过
f = new Boolean[n][m][101];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
for (int k = 0; k < 101; ++k) {
f[i][j][k] = false;
}
}
}
// 计算初始剩余油量
int st = mid - g[0][0];
// 将起点加入优先队列
pq.add(new int[] { g[0][0], st, 0, 0 });
f[0][0][st] = true;
// 开始广度优先搜索
while (pq.size() > 0) {
int[] tp = pq.poll();
int val = tp[1], x = tp[2], y = tp[3];
// 如果已经到达终点,返回true
if (x == n - 1 && y == m - 1) {
return true;
}
// 遍历四个方向
for (int k = 0; k < 4; k++) {
int nx = x + nxt[k][0], ny = y + nxt[k][1];
// 检查新的位置是否在地图范围内并且不是障碍物
if (nx < 0 || nx >= n || ny < 0 || ny >= m || g[nx][ny] == 0) {
continue;
}
int dval = val - g[nx][ny];
// 如果当前油量可以到达新位置
if (dval >= 0) {
int need = tp[0] + g[nx][ny];
// 如果新位置是加油站,重置油量
if (g[nx][ny] == -1) {
need += 1;
dval = 100;
}
// 如果新位置以及剩余油量组合没有被访问过,加入优先队列
if (!f[nx][ny][dval]) {
pq.add(new int[] { need, dval, nx, ny });
f[nx][ny][dval] = true;
}
}
}
}
return false;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 读取地图的行数和列数
String[] tmp = sc.nextLine().split(",");
n = Integer.parseInt(tmp[0]);
m = Integer.parseInt(tmp[1]);
g = new int[n][m];
// 读取地图数据
for (int i = 0; i < n; i++) {
tmp = sc.nextLine().split(",");
for (int j = 0; j < m; j++) {
g[i][j] = Integer.parseInt(tmp[j]);
}
// 起点是障碍物,直接返回-1
if (g[0][0] == 0) {
System.out.println(-1);
return;
}
}
// 二分搜索初始油量
int left = 0, right = 100;
int res = inf;
while (left <= right) {
int mid = left + (right - left) / 2;
if (check(mid)) {
right = mid - 1;
res = mid;
} else {
left = mid + 1;
}
}
// 如果起点是加油站,且找到了结果,输出0
if (g[0][0] == -1 && res != inf) {
System.out.println(0);
} else {
// 输出结果
if (res == inf) {
System.out.println(-1);
} else {
System.out.println(res);
}
}
}
}
Python3
import heapq
inf = int(1e9)
nxt = [(0, 1), (1, 0), (0, -1), (-1, 0)]
def check(g, n, m, mid):
if g[0][0] > mid:
return False
pq = []
f = [[[False] * 101 for _ in range(m)] for _ in range(n)]
st = mid - g[0][0]
heapq.heappush(pq, (g[0][0], st, 0, 0))
f[0][0][st] = True
while pq:
val, st, x, y = heapq.heappop(pq)
if x == n - 1 and y == m - 1:
return True
for dx, dy in nxt:
nx, ny = x + dx, y + dy
if 0 <= nx < n and 0 <= ny < m and g[nx][ny] != 0:
dval = st - g[nx][ny]
if dval >= 0:
need = val + g[nx][ny]
if g[nx][ny] == -1:
need += 1
dval = 100
if not f[nx][ny][dval]:
heapq.heappush(pq, (need, dval, nx, ny))
f[nx][ny][dval] = True
return False
def main():
data = input().split(',')
n, m = int(data[0]), int(data[1])
g = []
idx = 2
for i in range(n):
row = list(map(int,input().split(',')))
g.append(row)
if g[0][0] == 0:
print(-1)
return
left, right = 0, 100
res = inf
while left <= right:
mid = (left + right) // 2
if check(g, n, m, mid):
right = mid - 1
res = mid
else:
left = mid + 1
if g[0][0] == -1 and res != inf:
print(0)
elif res == inf:
print(-1)
else:
print(res)
if __name__ == '__main__':
main()
C++
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
const int inf = 1e9;
int n, m;
vector<vector<int>> g;
vector<vector<vector<bool>>> f;
int nxt[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
bool check(int mid) {
if (g[0][0] > mid) return false;
priority_queue<vector<int>, vector<vector<int>>, greater<>> pq;
f.assign(n, vector<vector<bool>>(m, vector<bool>(101, false)));
int st = mid - g[0][0];
pq.push({g[0][0], st, 0, 0});
f[0][0][st] = true;
while (!pq.empty()) {
auto tp = pq.top(); pq.pop();
int val = tp[1], x = tp[2], y = tp[3];
if (x == n - 1 && y == m - 1) return true;
for (int k = 0; k < 4; k++) {
int nx = x + nxt[k][0], ny = y + nxt[k][1];
if (nx < 0 || nx >= n || ny < 0 || ny >= m || g[nx][ny] == 0) continue;
int dval = val - g[nx][ny];
if (dval >= 0) {
int need = tp[0] + g[nx][ny];
if (g[nx][ny] == -1) {
need += 1;
dval = 100;
}
if (!f[nx][ny][dval]) {
pq.push({need, dval, nx, ny});
f[nx][ny][dval] = true;
}
}
}
}
return false;
}
vector<int> split(string& s){
int x=0,f=1;
vector<int> res;
for(auto&i:s){
if(i==','){
res.push_back(x*f);
x=0;
f=1;
}else if(i=='-'){
f=-1;
}else{
x=x*10+i-'0';
}
}
res.push_back(x*f);
return res;
}
int main() {
string tmp;
getline(cin,tmp);
vector<int> v=split(tmp);
n=v[0];
m=v[1];
for (int i = 0; i < n; i++){
getline(cin,tmp);
v=split(tmp);
g.push_back(v);
}
if (g[0][0] == 0) {
cout << -1 << endl;
return 0;
}
int left = 0, right = 100, res = inf;
while (left <= right) {
int mid = left + (right - left) / 2;
if (check(mid)) {
right = mid - 1;
res = mid;
} else {
left = mid + 1;
}
}
if (g[0][0] == -1 && res != inf) {
cout << 0 << endl;
} else {
cout << (res == inf ? -1 : res) << endl;
}
return 0;
}
C语言
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define INF 1000000000
struct Node {
int cost;
int fuel;
int x;
int y;
};
int n, m;
int g[100][100];
bool f[100][100][101];
int dir[4][2] = { {0, 1}, {1, 0}, {0, -1}, {-1, 0} };
bool check(int mid) {
if (g[0][0] > mid) return false;
struct Node pq[1000000];
int pq_size = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
for (int k = 0; k <= 100; k++)
f[i][j][k] = false;
int startFuel = mid - g[0][0];
pq[pq_size++] = (struct Node) {
g[0][0], startFuel, 0, 0
};
f[0][0][startFuel] = true;
while (pq_size > 0) {
struct Node node = pq[--pq_size];
int cost = node.cost;
int fuel = node.fuel;
int x = node.x;
int y = node.y;
if (x == n - 1 && y == m - 1) return true;
for (int k = 0; k < 4; k++) {
int nx = x + dir[k][0];
int ny = y + dir[k][1];
if (nx < 0 || nx >= n || ny < 0 || ny >= m || g[nx][ny] == 0) continue;
int remainingFuel = fuel - g[nx][ny];
if (remainingFuel >= 0) {
int newCost = cost + g[nx][ny];
if (g[nx][ny] == -1) {
newCost++;
remainingFuel = 100;
}
if (!f[nx][ny][remainingFuel]) {
pq[pq_size++] = (struct Node) {
newCost, remainingFuel, nx, ny
};
f[nx][ny][remainingFuel] = true;
}
}
}
}
return false;
}
char tmp[100005];
int main() {
scanf("%d,%d", &n, &m);
gets(tmp);
for (int i = 0; i < n; i++) {
gets(tmp);
int sz=strlen(tmp);
int p=0;
int x=0;
int f=1;
for(int j=0;j<sz;++j){
if(tmp[j]=='-'){
f=-1;
}else if(tmp[j]==','){
g[i][p]=x*f;
p+=1;
x=0;
f=1;
}else{
x=x*10+tmp[j]-'0';
}
}
g[i][p]=x*f;
}
if (g[0][0] == 0) {
printf("-1\n");
return 0;
}
int left = 0, right = 100;
int res = INF;
while (left <= right) {
int mid = left + (right - left) / 2;
if (check(mid)) {
right = mid - 1;
res = mid;
} else {
left = mid + 1;
}
}
if (g[0][0] == -1 && res != INF) {
printf("0\n");
} else {
printf("%d\n", res == INF ? -1 : res);
}
return 0;
}
JsNode
const rl = require("readline").createInterface({ input: process.stdin, output: process.stdout, });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void async function () {
const inf = 1e9;
const directions = [[0, 1], [1, 0], [0, -1], [-1, 0]];
let n, m, g=[], f;
let pq = [];
function check(mid) {
if (g[0][0] > mid) return false;
pq = [];
f = Array.from({ length: n }, () => Array.from({ length: m }, () => Array(101).fill(false)));
let st = mid - g[0][0];
pq.push([g[0][0], st, 0, 0]);
f[0][0][st] = true;
while (pq.length) {
pq.sort((a, b) => a[0] - b[0]);
let [val, st, x, y] = pq.pop();
if (x === n - 1 && y === m - 1) return true;
for (let [dx, dy] of directions) {
let nx = x + dx, ny = y + dy;
if (nx < 0 || nx >= n || ny < 0 || ny >= m || g[nx][ny] === 0) continue;
let dval = st - g[nx][ny];
if (dval >= 0) {
let need = val + g[nx][ny];
if (g[nx][ny] === -1) {
need += 1;
dval = 100;
}
if (!f[nx][ny][dval]) {
pq.push([need, dval, nx, ny]);
f[nx][ny][dval] = true;
}
}
}
}
return false;
}
let tmp=(await readline()).split(",").map(Number);
n=tmp[0];
m=tmp[1];
for (let i = 0; i < n; i++) {
let row=(await readline()).split(",").map(Number);
g.push(row);
}
if (g[0][0] === 0) {
console.log(-1);
return;
}
let left = 0, right = 100;
let res = inf;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
if (check(mid)) {
right = mid - 1;
res = mid;
} else {
left = mid + 1;
}
}
if (g[0][0] === -1 && res !== inf) {
console.log(0);
} else {
console.log(res === inf ? -1 : res);
}
}()
Go
package main
import (
"container/heap"
"fmt"
"strconv"
"strings"
)
const inf = 1e9
type Node struct {
cost int
fuel int
x int
y int
}
type PriorityQueue []*Node
func (pq PriorityQueue) Len() int { return len(pq) }
func (pq PriorityQueue) Less(i, j int) bool {
return pq[i].cost < pq[j].cost
}
func (pq PriorityQueue) Swap(i, j int) {
pq[i], pq[j] = pq[j], pq[i]
}
func (pq *PriorityQueue) Push(x interface{}) {
item := x.(*Node)
*pq = append(*pq, item)
}
func (pq *PriorityQueue) Pop() interface{} {
old := *pq
n := len(old)
item := old[n-1]
*pq = old[0 : n-1]
return item
}
var (
dirs = [][2]int{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}
n, m int
g [][]int
f [][][]bool
)
func check(mid int) bool {
if g[0][0] > mid {
return false
}
pq := &PriorityQueue{}
heap.Init(pq)
f = make([][][]bool, n)
for i := 0; i < n; i++ {
f[i] = make([][]bool, m)
for j := 0; j < m; j++ {
f[i][j] = make([]bool, 101)
}
}
st := mid - g[0][0]
heap.Push(pq, &Node{g[0][0], st, 0, 0})
f[0][0][st] = true
for pq.Len() > 0 {
tp := heap.Pop(pq).(*Node)
val, st, x, y := tp.cost, tp.fuel, tp.x, tp.y
if x == n-1 && y == m-1 {
return true
}
for _, dir := range dirs {
nx, ny := x+dir[0], y+dir[1]
if nx < 0 || nx >= n || ny < 0 || ny >= m || g[nx][ny] == 0 {
continue
}
dval := st - g[nx][ny]
if dval >= 0 {
need := val + g[nx][ny]
if g[nx][ny] == -1 {
need++
dval = 100
}
if !f[nx][ny][dval] {
heap.Push(pq, &Node{need, dval, nx, ny})
f[nx][ny][dval] = true
}
}
}
}
return false
}
func main() {
var input string
fmt.Scan(&input)
strSlice := strings.Split(input, ",")
intSlice := make([]int, len(strSlice))
for i, s := range strSlice {
num, err := strconv.Atoi(s)
if err!= nil {
return
}
intSlice[i] = num
}
n=intSlice[0]
m=intSlice[1]
g = make([][]int, n)
for i := 0; i < n; i++ {
g[i] = make([]int, m)
fmt.Scanln(&input)
strSlice := strings.Split(input, ",")
for j, s := range strSlice {
num, err := strconv.Atoi(s)
if err!= nil {
return
}
g[i][j] = num
}
}
if g[0][0] == 0 {
fmt.Println(-1)
return
}
left, right, res := 0, 100, 999999
for left <= right {
mid := int((left + right) / 2)
if check(mid) {
right = mid - 1
res = mid
} else {
left = mid + 1
}
}
if g[0][0] == -1 && res != 999999 {
fmt.Println(0)
} else {
fmt.Println(res)
}
}