编程题:跳石板

题目描述

小易来到了一条石板路前,每块石板上从1挨着编号为:1、2、3.......
这条石板路要根据特殊的规则才能前进:对于小易当前所在的编号为K的 石板,小易单次只能往前跳K的一个约数(不含1和K)步,即跳到K+X(X为K的一个非1和本身的约数)的位置。 小易当前处在编号为N的石板,他想跳到编号恰好为M的石板去,小易想知道最少需要跳跃几次可以到达。
例如:
N = 4,M = 24:
4->6->8->12->18->24
于是小易最少需要跳跃5次,就可以从4号石板跳到24号石板

输入描述:

输入为一行,有两个整数N,M,以空格隔开。 (4 ≤ N ≤ 100000) (N ≤ M ≤ 100000)

输出描述:

输出小易最少需要跳跃的步数,如果不能到达输出-1
示例1

输入

复制
4 24

输出

复制
5

思路:

使用动态规划:如果当前位置是不能到达的,直接返回,如果可到达,计算当前位置能去的所有位置,如果到达当前位置所需次数+1小于到达位置的当前最小次数,替换它

代码:

package com.example.shirodemo;

import java.util.*;

/**
 * Created by ASUS on 2018/7/8
 *
 * @Authod Grey Wolf
 */
public class Practice {

    public static void main(String[] args) {
        Practice practice = new Practice();
        practice.sys();
    }

    private void sys() {
        Scanner scan = new Scanner(System.in);
        System.out.println("输入整数n和m表示起点和终点:");
        while (scan.hasNext()) {
            int n = scan.nextInt();
            int m = scan.nextInt();
            System.out.println(leastJumpTime(n, m));
        }

    }

    /**
     * 动态规划
     *
     * @param n 起点
     * @param m 终点
     * @return
     */
    private int leastJumpTime(int n, int m) {
        if (m == n) {
            return 0;
        }
        //算上起点和终点的步数
        int steps = m - n + 1;
        //规划的 量到达每个位置需要的最小步数
        int[] dp = new int[steps];
        //起点
        dp[0] = 0;
        int i;
        for (i = 1; i < steps; i++) {
            //初始化表示后续位置都不能到达
            dp[i] = Integer.MAX_VALUE;
        }
        for (i = 0; i < steps; i++) {
            //0对应n石板,steps-1=m-n对应的m石板
            if (dp[i]==Integer.MAX_VALUE){
                dp[i]=0;
                continue;
            }
            //i+n是石板号
            ArrayList<Integer>list=getAppNums(i+n);
            for (int j=0;j<list.size();j++){
                int x=list.get(j);
                if (i+n+x<=m){
                    dp[i+x]=Math.min(dp[i+x],dp[i]+1);
                }
            }
        }
        if (dp[steps-1]==0){
            return -1;
        }else {
            return dp[steps-1];
        }
    }

    /**
     * 求因素集合
     * @param n
     * @return
     */
    private ArrayList<Integer> getAppNums(int n) {
        ArrayList<Integer>list=new ArrayList<>();
        int i;
        for (i=2;i<=Math.sqrt(n);i++){
            if (n%i==0){
                list.add(i);
                if (n/i!=i){
                    list.add(n/i);
                }
            }
        }
        return list;
    }


}

效果:

输入整数n和m表示起点和终点:
4 24
5

我的座右铭:不会,我可以学;落后,我可以追赶;跌倒,我可以站起来;我一定行。

猜你喜欢

转载自blog.csdn.net/weixin_39220472/article/details/80961112