给定一个非负整数数组nums,假定最开始处于下标为0的位置,数组里面的每个元素代表下一跳能够跳跃的最大长度,如果可以跳到数组最后一个位置,请你求出跳跃路径中所能获得的最多的积分。
1.如果能够跳到数组最后一个位置,才能计算所获得的积分,否则积分值为-1
2.如果无法跳跃(即数组长度为0),也请返回-1
3.数据保证返回的结果不会超过整形范围,即不会超过
数据范围:
第一行输入一个正整数 n 表示数组 nums的长度第二行输入 n 个整数,表示数组 nums 的所有元素的值
输出能获得的最多的积分
6 2 4 2 1 0 100
106
首先位于nums[0]=2,然后可以跳1步,到nums[1]=4的位置,积分=2+4=6,再跳到nums[5]=100的位置,积分=6+100=106
这样保证既能跳到数组最后一个元素,又能保证获取的积分最多
6 2 4 0 2 0 100
108
跳跃路径为:2=>4=>2=>100,总共为108
6 2 3 2 1 0 100
-1
跳不到最后一个位置,返回-1
import java.util.Scanner; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); // 注意 hasNext 和 hasNextLine 的区别 int n = in.nextInt(); int[] num = new int[n]; int[] f = new int[n]; int i; // 动态规划的过程,判断是否可达,将可达信息存储在f[i]中 for(i = 0; i < n; i++){ num[i] = in.nextInt(); } f[0] = num[0]; for(i = 1; i < n - 1 && i <= f[i-1]; i++){ f[i] = Math.max(f[i-1], num[i] + i); } // 输出不可达信息 if(f[i - 1] < n - 1){ System.out.print(-1); return; } // 倒推,贪婪,从后往前只要可达的点都选择 int sum = num[n - 1]; int pos = n - 1; for(i = n - 2; i >= 0; i--){ if(f[i] != 0 && num[i] + i >= pos){ pos = i; sum += num[i]; } } System.out.print(sum); } }
#include <iostream> #include <vector> using namespace std; int main() { int n; cin>>n; vector<int> arr(n); for(int i=0; i<n; i++){ cin>>arr[i]; } vector<int> dp(n,-1); dp[n-1] = arr[n-1]; int pos = n-1, pre = pos; while(true){ int j=pos-1; while(j>=0){ if(arr[j]+j>=pos){ //说明从j位置可以一步跳到pos位置 dp[j] = arr[j]+dp[pos]; pos = j; } j--; } if(pre==pos||pos==0){ //pos没有向前推 break; } pre = pos; } cout<<dp[0]; return 0; }
Scanner in = new Scanner(System.in); int n = in.nextInt(); if (n == 0) { System.out.println("-1"); return; } int[] nums = new int[n]; int[] dp = new int[n]; //保存 i 的位置是否可以到达的状态. 1可以到达, 0不可以到达 for (int i = 0; i < n; i++) { nums[i] = in.nextInt(); } //dp 动态规划 : 从数组最后往前遍历.. 能到达终点的终点的位置 标记 1. dp[n - 1] = 1; //终点位置标记1 for (int i = n - 1; i >= 0; i--) { int num = nums[i]; for (int j = i + num; j >= i; j--) { //遍历能到达的点. if (j >= n - 1 || dp[j] == 1) {//超过了终点 或者 到达的点 确定可以到达终点 dp[i] = 1; break; } //否则 dp[i] 保持 0 } } if (dp[0] == 0) { //开始的位置不能到达终点的话, 那么直接 返回-1 System.out.println("-1"); return; } int max = 0; for (int i = 0; i < n; i++) { //能到达的点都加上积分 if (dp[i] == 1) max += nums[i]; } System.out.println(max);
def solution(n,nums): if not n: return -1 maxL = nums[0] dp = [nums[i] for i in range(n)] #以nums[i]为结尾的序列所能获得的maxVal for i in range(1,n): #1)从nums[0:i)不能到达第i个位置,即当前所能到达的 maxL < i,则无法跳到终点。 #2)maxL >= i, 则从nums[0:i)某个位置一定能跳到位置i if maxL < i: return -1 maxL = max(maxL, i+nums[i])#更新maxL #往回寻找能跳到位置i的最大值位置 j = i-1 #目标位置就是距离位置 i 最近且能到达位置 i 的位置!! #假设有且只有k,j都能到达 i,且 k < j < i。则最优解只可能是由k跳到j,再由j跳到i。因为nums值都>=0。 while(nums[j] + j < i): j -= 1 #更新以位置i为结尾的序列的maxVal dp[i] = max(dp[i],nums[i]+dp[j]) return dp[-1] if __name__ == "__main__": n = int(input()) data = list(map(int,input().split())) res = solution(n,data) print(res)
import java.util.*; public class Main{ public static void main(String[] args){ Scanner in=new Scanner(System.in); int n=in.nextInt(); int[] a=new int[n]; for(int i=0;i<n;i++){ a[i]=in.nextInt(); } int[] dp=new int[n]; Arrays.fill(dp,-1); dp[0]=a[0]; for(int i=0;i<n-1;i++){ if(dp[i]<0||a[i]==0){ continue; } int end=Math.max(n,i+a[i]+1); for(int s=i+1;s<end;s++){ dp[s]=Math.max(dp[s],dp[i]+a[s]); } } System.out.println(dp[n-1]); } }这组测试用例不能通过: