跳石板_牛客网

链接:https://www.nowcoder.com/questionTerminal/4284c8f466814870bae7799a07d49ec8
来源:牛客网

小易来到了一条石板路前,每块石板上从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. res数组中存储着从起点到index位置所需最小步数(每部步长均为该步起点的约数),默认均为不可达(INT_MAX);
  2. 从起点(i = N)开始遍历,如果当前位置不可达,直接进入下一次循环,表示该位置不可用;
  3. 否则,计算从位置i走,可选的步长有哪些(vector v),遍历v,更新从位置i走一步(步长为it)可到达的位置的res数组对应值,即从起点到位置i+it的当前最少步数。(分位置i+it原本可达和不可达两种情况,详细论述见代码中注释)
  4. 最终,res数组中存储着从位置N到[N~M]间每个位置的最少步数的确定值
#include <iostream>
#include <algorithm>
#include <climits>
using namespace std;

void func(int x, vector<int>& v) //求x除1和其本身的约数
{
    int ret = 0;
    for(int i = 2; i*i <= x; ++i)
    {
        if(x % i == 0)
        {
            v.push_back(i);
            if(x / i != i)
                v.push_back(x / i);
        }
    }
}

int main()
{
    int N, M;
    while(cin >> N && cin >> M)
    {
        vector<int> res(M+1, INT_MAX); //记录从N到该位置(cur_index)所需步数,INT_MAX为不可达,初始值为INT_MAX
        res[N] = 0; 
        for(int i = N; i < M; ++i)
        {
            if(res[i] == INT_MAX)
                continue;
            //以下,位置i可达
            vector<int> v; 
            func(i, v); //v中为i的约数,即从位置i走,可选的步长
            for(const auto it : v)
            {
                if(i + it <= M && res[i+it] != INT_MAX) 
                    //从位置i走it步,不超出终点M;
                    //位置i+it原本可到达,更新为较小的
                    res[i+it] = min(res[i+it], res[i]+1); 
                    //从位置i走,一次it步长可到达位置i+it,
                    //即从N到达位置i+it,所以一个可选方案是走ret[i]+1步,与原本的值保留较小的
                else if(i + it <= M)
                    //位置i+it本不可达,现在已知从位置i走一次步长为it可到达该位置,因此更新为ret[i]+1
                    res[i+it] = res[i]+1; 
            }
        }
        if(res[M] == INT_MAX) //每次步长为约数,不可达
            cout << -1 << endl;
        else                  //可达
            cout << res[M] << endl;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/dabai56/p/10971184.html