您的位置:首页 > 编程语言 > Java开发

跳跃游戏(一,二)

2017-10-15 12:11 260 查看
跳跃游戏二

题目:


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

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

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

例如:

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(1≤n≤500),接下来的一行 nnn 个整数,输入数组 AiA_iA​i​​。

输出格式

如果能跳到最后一个下标,输出
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
;
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");
}
}
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息