题目
小易来到了一条石板路前,每块石板上从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
思路
循环i~[n,m], 得到i的约数集合*it
更新可以跳到的下一个点的最短的距离
要么保留,要么就是第i点+1
res[i+*it] = min(res[i+*it],res[i]+1);
注意
- 初始化的时候 和 最后结果输出 以及中间的 判断
res[n]=1; //第一个设置为1,为了 if(res[i] == 0)这句话,启动,所以后面结果是res[m]-1
if(res[i] == 0) continue;
- 每次更新的时候都必须判断 是否超出了m,否则数组越界
- 更新时还需判断是否为0,否则直接为
res[i]+1
代码
#include<iostream>
#include<vector>
#include<set>
#include<math.h>
using namespace std;
// 得到n的约数,除了1和它本身
void get_yue_shu(int n, vector<int>&a){
for(int i=2;i<=sqrt(n);i++){
if(n%i==0){
a.push_back(i);
if(n/i != i)
a.push_back(n/i);
}
}
}
void minJump(int n, int m)
{
vector<int> res(m+1,0); //m+1 vector 0
res[n]=1; //第一个设置为1,为了 if(res[i] == 0)这句话,启动,所以后面结果是res[m]-1
for(int i = n;i<=m;i++)
{
vector<int> a; //约数的集合
get_yue_shu(i,a);
if(res[i] == 0)
continue;
// iterator迭代器要用vector<int>::
for(vector<int>::iterator it = a.begin();it!=a.end();it++)
{
if((i+*it)<=m&&res[i+*it]!=0)
res[i+*it] = min(res[i+*it],res[i]+1);
else if((i+*it)<=m)
res[i+*it] = res[i]+1;
}
}
if(res[m]==0)
cout<<-1<<endl;
else
cout<<res[m]-1<<endl;
}
int main(){
int n,m;
cin>>n>>m;
minJump(n,m);
}