Given an array A
(index starts at 1
) consisting of N integers: A1, A2, ..., AN and an integer B
. The integer B
denotes that from any place (suppose the index is i
) in the array A
, you can jump to any one of the place in the array A
indexed i+1
, i+2
, …, i+B
if this place can be jumped to. Also, if you step on the index i
, you have to pay Ai coins. If Ai is -1, it means you can’t jump to the place indexed i
in the array.
Now, you start from the place indexed 1
in the array A
, and your aim is to reach the place indexed N
using the minimum coins. You need to return the path of indexes (starting from 1 to N) in the array you should take to get to the place indexed N
using minimum coins.
If there are multiple paths with the same cost, return the lexicographically smallest such path.
If it's not possible to reach the place indexed N then you need to return an empty array.
Example 1:
Input: [1,2,4,-1,2], 2 Output: [1,3,5]
Example 2:
Input: [1,2,4,-1,2], 1 Output: []
Note:
- Path Pa1, Pa2, ..., Pan is lexicographically smaller than Pb1, Pb2, ..., Pbm, if and only if at the first
i
where Pai and Pbi differ, Pai < Pbi; when no suchi
exists, thenn
<m
. - A1 >= 0. A2, ..., AN (if exist) will in the range of [-1, 100].
- Length of A is in the range of [1, 1000].
- B is in the range of [1, 100].
给一个数组A,数组元素的值代表cost,一个整数B表示能走的最大步数。从第1个位置开始走,每次能走的步数是B步以内,走到某个位置就要付出该位置的cost,目标是到达最末尾位置,使得付出总cost值最小,输出所有路径。如果某个位置是-1,不可以走这个位置。如果有多个路径,输出按字母顺序排列。
解法:DP, 从后往前跳。首先判断最后一个位置是否为-1,如果是说明无法到达最后位置,返回空。用一个一维数组dp记录跳到i位置所用的最小cost, 从i位置跳时有B种跳法,再去判断每一个跳法的dp值。
dp[i] = A[i] + dp[j] (dp[j]为从B种跳法中的一种的dp值)
Python:
# Time: O(n * B)
# Space: O(n)
class Solution(object):
def cheapestJump(self, A, B):
"""
:type A: List[int]
:type B: int
:rtype: List[int]
"""
result = []
if not A or A[-1] == -1:
return result
n = len(A)
dp, next_pos = [float("inf")] * n, [-1] * n
dp[n-1] = A[n-1]
for i in reversed(xrange(n-1)):
if A[i] == -1:
continue
for j in xrange(i+1, min(i+B+1,n)):
if A[i] + dp[j] < dp[i]:
dp[i] = A[i] + dp[j]
next_pos[i] = j
if dp[0] == float("inf"):
return result
k = 0
while k != -1:
result.append(k+1)
k = next_pos[k]
return result
C++:
class Solution {
public:
vector<int> cheapestJump(vector<int>& A, int B) {
if (A.back() == -1) return {};
int n = A.size();
vector<int> res, dp(n, INT_MAX), pos(n, -1);
dp[n - 1] = A[n - 1];
for (int i = n - 2; i >= 0; --i) {
if (A[i] == -1) continue;
for (int j = i + 1; j <= min(i + B, n - 1); ++j) {
if (dp[j] == INT_MAX) continue;
if (A[i] + dp[j] < dp[i]) {
dp[i] = A[i] + dp[j];
pos[i] = j;
}
}
}
if (dp[0] == INT_MAX) return res;
for (int cur = 0; cur != -1; cur = pos[cur]) {
res.push_back(cur + 1);
}
return res;
}
};
C++:
class Solution {
public:
vector<int> cheapestJump(vector<int>& A, int B) {
if (A.back() == -1) return {};
int n = A.size();
vector<int> res, dp(n, INT_MAX), pos(n, -1), len(n, 0);
dp[0] = 0;
for (int i = 0; i < n; ++i) {
if (A[i] == -1) continue;
for (int j = max(0, i - B); j < i; ++j) {
if (dp[j] == INT_MAX) continue;
int t = A[i] + dp[j];
if (t < dp[i] || (t == dp[i] && len[i] < len[j] + 1)) {
dp[i] = t;
pos[i] = j;
len[i] = len[j] + 1;
}
}
}
if (dp[n - 1] == INT_MAX) return res;
for (int cur = n - 1; cur != -1; cur = pos[cur]) {
res.insert(res.begin(), cur + 1);
}
return res;
}
};
C++:
class Solution {
public:
vector<int> cheapestJump(vector<int>& A, int B) {
vector<int> result;
if (A.empty() || A.back() == -1) {
return result;
}
const int n = A.size();
vector<int> dp(n, numeric_limits<int>::max()), next(n, -1);
dp[n - 1] = A[n - 1];
for (int i = n - 2; i >= 0; --i) {
if (A[i] == -1) {
continue;
}
for (int j = i + 1; j <= min(i + B, n - 1); ++j) {
if (dp[j] == numeric_limits<int>::max()) {
continue;
}
if (A[i] + dp[j] < dp[i]) {
dp[i] = A[i] + dp[j];
next[i] = j;
}
}
}
if (dp[0] == numeric_limits<int>::max()) {
return result;
}
int k = 0;
while (k != -1) {
result.emplace_back(k + 1);
k = next[k];
}
return result;
}
};
类似题目:
[LeetCode] 198. House Robber 打家劫舍
[LeetCode] 213. House Robber II 打家劫舍 II
[LeetCode] 45. Jump Game II 跳跃游戏 II
All LeetCode Questions List 题目汇总