跳跃游戏(一,二)

跳跃游戏二
题目:

给定一个非负整数数组,假定你的初始位置为数组第一个下标。

数组中的每个元素代表你在那个位置能够跳跃的最大长度。

你的目标是到达最后一个下标,并且使用最少的跳跃次数。

例如:

A=[2,3,1,1,4],到达最后一个下标的最少跳跃次数为2。(先跳跃111 步,从下标0 到1,然后跳3 步,到达最后一个下标。一共两次)

输入格式

第一行输入一个正整数 n(1≤n≤100)n,接下来的一行,输入 n 个整数,表示数组 A

输出格式

最后输出最少的跳跃次数。

样例输入
5
3 1 1 1 1
样例输出
2
代码:
import java.util.*;

public class Main{
	public static void main(String args[])
    {
		Scanner in =new Scanner(System.in);
		int num=in.nextInt();
		int []a=new int[num];
		int []dp=new int[num];//dp表示的是从起点跳到当前位置所需的次数
		for(int i=0;i<num;i++) {
			a[i]=in.nextInt();
			dp[i]=0;
		}
		for(int i=0;i<num;i++) {
			for(int j=1;j<=a[i];j++) {
				if(i+j<num) {
					if(dp[i+j]<=0) {
					dp[i+j]=dp[i]+1;
				}else if(dp[i]+1<dp[i+j]) {
					dp[i+j]=dp[i]+1;
				}
				}
			}
		}
		System.out.println(dp[num-1]);
    }
}
这个程序通过基本的测试用例也都是没问题,但是它还是存在这一些问题。。。。。
本来没有发现,其实这个程序是有错误的,当我们输入的数组中存在0的时候怎么办,这种情况没有考虑到。。。
例如当我们输入的数组为:{1,0,2,3,4}时,这时从第二个节点是不能在进行跳跃时,此时这个数组是无解的,这种情况也必须考虑到。
所以需要进行一下更正:
在第一个for循环中,i<num的判断条件,加一个与 dp[i]!=0;这就是说明,当它不能从第一个节点跳过去时,后面的节点就不需要进行判断了,
我们判断的节点,必须是可以从第一个节点跳过去的才可以。
但是当我们加入这个与的判定条件时,我们又会发现问题,因为我们默认的dp数组都是0,当我们加入这个判断条件时,我们会发现第一个节点,
就是不能通过for循环的,所以我们还需要做出一些改变。就是当判断第一个节点时,我们先修改dp的值,然后判断完之后,我们在改回来。。。
这个方法可能挺不好的,但是目前我还没有想到更好的解决办法,所以先这样进行訂正,以后想到更好的方法,在进行修改。
修改之后代码如下:
import java.util.*;

public class Main{
	public static void main(String args[])
    {
		Scanner in =new Scanner(System.in);
		int num=in.nextInt();
		int []a=new int[num];
		int []dp=new int[num];//dp表示的是从起点跳到当前位置所需的次数
		for(int i=0;i<num;i++) {
			a[i]=in.nextInt();
			dp[i]=0;
		}
		dp[0]=1;
		for(int i=0;i<num&&dp[i]!=0;i++) {
			dp[0]=0;
			for(int j=1;j<=a[i];j++) {
				if(i+j<num) {
					if(dp[i+j]<=0) {
					dp[i+j]=dp[i]+1;
				}else if(dp[i]+1<dp[i+j]) {
					dp[i+j]=dp[i]+1;
				}
				}
			}
		}
		if(dp[num-1]<=0)System.out.println("无解,跳不到最后一个节点 ");
		else System.out.println(dp[num-1]);
    }
}
跳跃游戏一:
其实也可以用这个方法来解,只需要将上面的输出做一个判断就好,如果dp[num-1]>0 则为true,否则为false。但是还有一点要注意,就是当只输入一个元素时,
对跳跃游戏一来说可能有些问题,因为此时dp[0]=0,判断是false的,但是结果应该为true,所以这时只要修改一下dp[0]=0 的位置就好。
但是事实上跳跃游戏有更好的解决方法:基于贪心算法的

问题:

给定一个非负整数数组,假定你的初始位置为数组第一个下标。

数组中的每个元素代表你在那个位置能够跳跃的最大长度。

请确认你是否能够跳跃到数组的最后一个下标。

例如:A=[2,3,1,1,4] 能够跳跃到最后一个下标,输出true

A=[3,2,1,0,4] 不能跳跃到最后一个下标,输出false

输入格式

第一行输入一个正整数 n(1≤n≤500)n(1 \leq n \leq 500)n(1n500),接下来的一行 nnn 个整数,输入数组 AiA_iAi

输出格式

如果能跳到最后一个下标,输出true,否则输出false

样例输入
5
2 0 2 0 1

样例输出
true
代码:
import java.util.Scanner;

public class Main{  
    public static void main(String[] args) {  
        Scanner sc = new Scanner(System.in);  
        int n = sc.nextInt();  
        /* 
         * 思路:贪心算法; 
         * 从第一个数开始, 寻找可以一个可以跳最远的点; 
         * 例1:3 1 2 4 1 0 0 
         * 1.从第一个位置0,可以跳到位置1和位置2和位置3; 
         * 2.如果跳到位置1,那么最远就可以跳到位置(1+1); 
         * 3.如果跳到位置2,那么最远就可以跳到位置(2+2); 
         * 4.如果跳到位置3,那么最远就可以跳到位置(3+4); 
         * 5.故选择跳到位置3 ,重复1.2.3步; 
         *  
         * 算法分析: 
         * 1.如果选择跳到位置3 ,就无法跳到位置2和位置3, 那么会不会因此错过最优解? 答:不会! 
         * 2.因为任意位置1和位置2能到达的位置, 位置3都可以到达; 
         * 3.故不会错过最优解; 
         */  
        int[]a = new int[n];  
        for(int i= 0 ;i< n ;i++) {  
            a[i] = sc.nextInt();  
        }  
        int i;  
        int l;  //左边界       控制搜索的起始位置  
        int r;  //右边界       控制搜索的终止位置  
        for( i= 0 ;i< n && a[i]!= 0 ;) { //当a[i]==0 时 , 该位置为可到达的最远位置  
            r = i + a[i];  
            l = i + 1;   
            for(int j= i+1 ;j< n && j<= i+a[i] ;j++) {    //  
                if(j+a[j] >= r){ //遍历可到达位置 能到达的最远位置  
                    r = j+ a[j];    //更新左右边界  
                    l = j;  
                }  
            }  
            i = l;  //左边界  
              
        }  
        if(i< n-1) {  
            System.out.println("false");  
              
        }else{  
            System.out.println("true");  
        }  
    }  
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值