首页 > 试题广场 >

跳跃游戏(二)

[编程题]跳跃游戏(二)
  • 热度指数:3070 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定一个非负整数数组nums,假定最开始处于下标为0的位置,数组里面的每个元素代表下一跳能够跳跃的最大长度,如果可以跳到数组最后一个位置,请你求出跳跃路径中所能获得的最多的积分。
1.如果能够跳到数组最后一个位置,才能计算所获得的积分,否则积分值为-1
2.如果无法跳跃(即数组长度为0),也请返回-1
3.数据保证返回的结果不会超过整形范围,即不会超过
数据范围:




输入描述:
第一行输入一个正整数 n 表示数组 nums的长度
第二行输入 n 个整数,表示数组 nums 的所有元素的值


输出描述:
输出能获得的最多的积分
示例1

输入

6
2 4 2 1 0 100

输出

106

说明

首先位于nums[0]=2,然后可以跳1步,到nums[1]=4的位置,积分=2+4=6,再跳到nums[5]=100的位置,积分=6+100=106
这样保证既能跳到数组最后一个元素,又能保证获取的积分最多    
示例2

输入

6
2 4 0 2 0 100

输出

108

说明

跳跃路径为:2=>4=>2=>100,总共为108        
示例3

输入

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);
    }
}

编辑于 2024-03-09 08:08:35 回复(0)
#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;
}

编辑于 2023-12-30 18:25:02 回复(0)
import sys

for line in sys.stdin:
    a = line.split()
nums = [int(t) for t in a]
pos = len(nums)-1
v = nums[-1]

for i in range(len(nums)-2, -1, -1):
    if nums[i] >= pos - i:
       pos = i 
       v += nums[i]

if pos != 0:
    print(-1)
else:
    print(v)

发表于 2023-07-24 16:15:23 回复(0)
//动态回归 + 优先队列
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] array = new int[n];
        for (int i = 0; i < n; i++) {
            array[i] = scanner.nextInt();
        }
        Queue<int[]> queue = new PriorityQueue<>(new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o2[0] - o1[0];
            }
        });
        int[] dp =new int[n];
        Arrays.fill(dp, -1);
        dp[0] = array[0];
        queue.add(new int[]{dp[0], 0});
        for (int i = 1; i < n; i++) {
            while (!queue.isEmpty() && i - queue.peek()[1] > array[queue.peek()[1]]){
                queue.poll();
            }
            if (queue.isEmpty())
                break;
            dp[i] = queue.peek()[0] + array[i];
            queue.add(new int[]{dp[i], i});
        }
        System.out.println(dp[n - 1]);
    }
}
发表于 2023-03-03 21:02:30 回复(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);

发表于 2022-11-19 00:54:30 回复(0)
python3 前推法
时间复杂度O(n2)比倒推法O(n)高,但能通过测试。
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)


发表于 2022-07-26 15:41:31 回复(0)
n = int(input())
nums = list(map(int,input().split(' ')))
idx = n-1
res = 0
while idx>0:
    res += nums[idx]
    j = idx-1
    while j>=0 and nums[j]+j<idx:
        j-=1
    if j<0:
        break
    idx = j
if idx>0:
    print(-1)
else:
    print(res+nums[0])

发表于 2022-07-20 16:34:47 回复(0)
#include<iostream>
using namespace std;
intdp[100000];
intmain()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    intn;
    bool ans =true;
    cin >> n;
    int* num =newint[n];
    for(inti =0; i < n; ++i) {
        cin >> num[i];
        dp[i] =0;
    }
    dp[0] = num[0];
    for(inti =0; i < n; ++i) {
        for(intj = i +1; dp[i] && j <= i + num[i] && j < n; ++j) {
            dp[j] = max(dp[j], dp[i] + num[j]);
        }
    }
    if(dp[n -1] ==0)
        cout << -1;
    else
        cout << dp[n -1];
}
发表于 2022-07-11 14:42:14 回复(0)
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]);
       
        
    }
}
这组测试用例不能通过:
6
2 3 2 1 0 100
求解答
发表于 2022-07-01 10:28:28 回复(1)