“牛客网" 跳石板

”牛客网“跳石板

题目链接:https://www.nowcoder.com/practice/4284c8f466814870bae7799a07d49ec8?tpId=85&tqId=29852&tPage=2&rp=2&ru=/ta/2017test&qru=/ta/2017test/question-ranking

import java.util.ArrayList;
import java.util.Scanner;
import java.util.Stack;

/*
 * 超级变态跳台阶
 * 从台阶m到台阶n,每步只能跳当前台阶的因数(除了1和其本身),求跳到台阶m需要的最小步数
 * 使用mark[i]数组记录从台阶m跳到台阶i需要的最小步数
 * 初始时:只有mark[m]为0,其余为正无穷
 * 对于每一个i~[m,n-2],计算得到其因数temp,if(i+temp<=n)执行以下步骤:
 * 若mark[i+temp]>mark[i]+1,那么更新mark[i+temp]为mark[i]+1
 * 
 * 到i=n-2时,只有temp=2满足条件,直接跳到台阶n。因此不需要再遍历i=n-1以及i=n
 * 最终得到的mark[n]即所求结果
 * 
 * 进阶:
 * 打印出跳的路径
 * 新增一个数组,保存跳到该台阶经过的上一级台阶
 */
public class JumpSlate {
    private static int[] mark;
    private static int[] path;
    static int start;
    static int dest;
    public static void JumpSlate(){
        Scanner sc = new Scanner(System.in);
        int startSlate = sc.nextInt(); //起始台阶
        int destSlate = sc.nextInt(); //目标台阶
        start = startSlate;
        dest = destSlate;
        //给mark数组分配空间
        mark = new int[destSlate+1]; //记录到达每一个位置的最小步数
        path = new int[destSlate+1]; //记录到达当前台阶所经过的上一级台阶编号
        //初始化每一个值为正无穷,得到最终结果时仍保留为正无穷的台阶即为不可达
        for(int i=startSlate+1;i<=destSlate;i++){
            mark[i] = Integer.MAX_VALUE;
            path[i] = Integer.MAX_VALUE;
        }
        //设置初始台阶需要的步数为0
        mark[startSlate] = 0;
        path[startSlate] = startSlate;
        //遍历mark数组,对每一个台阶所需步数进行计算
        //i~[startSlate,destSlate-2]
        for(int i=startSlate;i<=destSlate-2;i++){
            ArrayList<Integer> factorList = calFactors(i);
            //对于跳j阶可以到达的台阶进行更新
            for(int j=0;j<factorList.size();j++){
                int thisStep = factorList.get(j);
                int toSlate = i+thisStep; //跳thisStep阶之后,可以从台阶i跳到台阶toSlate
                if(toSlate<=destSlate) //检查跳thisStep之后是否超出界限
                {
                    if(mark[toSlate]>mark[i]+1 && mark[i]!=Integer.MAX_VALUE) //如果toSlate台阶中保存的步数大于当前经过台阶i所需的步数
                    {
                        //更新mark[toSlate]中的值
                        //即更新到达toSlate的方式为经过i到达
                        mark[toSlate] = mark[i]+1;
                        path[toSlate] = i;
                    }
                }
                else{
                    continue;
                }
            }
        }
        int result = mark[destSlate];
        if(result==Integer.MAX_VALUE)
            result = -1;
        System.out.println("need step:"+result);
    } 

    /*
     * 计算因数,返回ArrayList类型因数列表
     */
    private static ArrayList<Integer> calFactors(int num){
        ArrayList<Integer> factors = new ArrayList<Integer>();
        for(int i=2;i<=Math.sqrt(num);i++){
            if(num%i==0){
                factors.add(i);
                if(i!=num/i) factors.add(num/i);
            }
        }
        return factors;
    } 

    public static void printPath(){
        if(path[dest]!=Integer.MAX_VALUE){ //如果当前目的地是可达的
            Stack<Integer> records = new Stack<>();
            int lastSlate = path[dest];
            while(lastSlate!=start){
                records.push(lastSlate);
                lastSlate = path[lastSlate];
            }
            System.out.print("path:");
            System.out.print(start+"->");
            while(!records.isEmpty())
            {
                System.out.print(records.pop()+"->");
            }
            System.out.println(dest);
        }
    }
}

解题思路参照 图论最短路径算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值