解题思路
- 使用 数组记录到达每个位置能获得的最大积分
- 对于每个位置 ,遍历其能跳到的所有位置
- 状态转移方程:
- 需要先判断位置是否可达,使用一个布尔数组记录可达性
- 最后检查终点是否可达,如果可达则返回 ,否则返回
代码
#include <iostream>
#include <vector>
using namespace std;
int maxScore(vector<int>& nums) {
int n = nums.size();
if (n == 0) return -1;
if (n == 1) return nums[0];
vector<bool> can_reach(n, false); // 记录位置是否可达
vector<int> dp(n, 0); // 记录到达每个位置的最大积分
can_reach[0] = true;
dp[0] = nums[0];
// 遍历每个位置
for (int i = 0; i < n; i++) {
if (!can_reach[i]) continue;
// 从当前位置能跳到的所有位置
for (int j = i + 1; j <= min(i + nums[i], n - 1); j++) {
can_reach[j] = true;
dp[j] = max(dp[j], dp[i] + nums[j]);
}
}
return can_reach[n-1] ? dp[n-1] : -1;
}
int main() {
int n;
cin >> n;
vector<int> nums(n);
for (int i = 0; i < n; i++) {
cin >> nums[i];
}
cout << maxScore(nums) << endl;
return 0;
}
import java.util.*;
public class Main {
public static int maxScore(int[] nums) {
int n = nums.length;
if (n == 0) return -1;
if (n == 1) return nums[0];
boolean[] canReach = new boolean[n];
int[] dp = new int[n];
canReach[0] = true;
dp[0] = nums[0];
for (int i = 0; i < n; i++) {
if (!canReach[i]) continue;
for (int j = i + 1; j <= Math.min(i + nums[i], n - 1); j++) {
canReach[j] = true;
dp[j] = Math.max(dp[j], dp[i] + nums[j]);
}
}
return canReach[n-1] ? dp[n-1] : -1;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] nums = new int[n];
for (int i = 0; i < n; i++) {
nums[i] = sc.nextInt();
}
System.out.println(maxScore(nums));
}
}
def maxScore(nums):
n = len(nums)
if n == 0:
return -1
if n == 1:
return nums[0]
can_reach = [False] * n # 记录位置是否可达
dp = [0] * n # 记录到达每个位置的最大积分
can_reach[0] = True
dp[0] = nums[0]
# 遍历每个位置
for i in range(n):
if not can_reach[i]:
continue
# 从当前位置能跳到的所有位置
for j in range(i + 1, min(i + nums[i] + 1, n)):
can_reach[j] = True
dp[j] = max(dp[j], dp[i] + nums[j])
return dp[n-1] if can_reach[n-1] else -1
n = int(input())
nums = list(map(int, input().split()))
print(maxScore(nums))
算法及复杂度
- 算法:动态规划
- 时间复杂度: - 对于每个位置都可能需要遍历后面的所有位置
- 空间复杂度: - 需要两个长度为n的数组
这道题是跳跃游戏的变体,除了要判断能否到达终点外,还需要计算最大积分。关键点在于:
-
需要同时维护两个数组:
- 数组记录每个位置是否可达
- 数组记录到达每个位置的最大积分
-
状态转移的过程:
- 只有当前位置 可达时才进行跳跃
- 对于可以跳到的每个位置 ,更新其可达性和最大积分
- 最大积分的更新公式:
-
特殊情况处理:
- 数组长度为 时返回
- 数组长度为 时直接返回
- 如果终点不可达,返回
这种方法能够保证找到所有可能的跳跃路径,并在其中选择积分最大的一条。