题目描述
小易来到了一条石板路前,每块石板上从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号石板
这条石板路要根据特殊的规则才能前进:对于小易当前所在的编号为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小于到达位置的当前最小次数,替换它 。代码:
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
我的座右铭:不会,我可以学;落后,我可以追赶;跌倒,我可以站起来;我一定行。