所用到的知识
STL中的vector容器
动态规划思想
算法中的min
编程思想
- 将1 - M个看成一排,为其取个名字叫Slab(数组),并在走之前将这一排石板都初始化为0,然后开始走,每到一块是班上就在这块是石板上写下到这里来的步数,如果脚下踩的这块石板上写的0,说明之前没有来过,那就不可能走到这里,跳过这个石板,重新走
2. 从起点开始对这一排石板Slab进行遍历,求出可以从这块石板出发走的步数(当前石板对应位置的所有约数) - 到达当前位置就要更新这块石板的上面写的步数,选择之前走的步数和现在走的步数中最小的卸载当前是石板上,如果之前没有到达过这块石板则更新为此时位置的最小步数 + 1,
4. 知道走到最后一块石版,或者下一次将要走到最后一块石板的时候,看之前有没有到过最后一块石板,如果有,就返回上面的步数(Slab[m]),如果没有就要返回-1
接下来就直接上代码,代码中也有注释
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;//计算该数的公约数
void Divisor(int n,vector<int>& buff)
{for(size_t i = 2; i <= sqrt(n); ++i){if(n%i == 0){buff.push_back(i);//如果这个数不是平方数,那么也将另一个数加入到列表中if(n/i != i)buff.push_back(n/i);}}
}int Jump_Slab(int n, int m)
{//存放从起始位置到每个位置所需要的步数vector<int> Slab(m+1,0);//从n位置走到n位置只需要1步,所以初始化为1Slab[n] = 1;for(size_t i = n; i < m; ++i){//如果这个位置为0,说明不能走到这个位置,跳出此次循环if(0 == Slab[i])continue;//存放i位置可以走的步数vector<int> Jump;Divisor(i,Jump);//Slab[Jump[j] + i]是当前可以走到的位置for(size_t j = 0; j < Jump.size(); ++j){//由位置i出发能到达的点为 stepNum[divNum[j]+i]if(Jump[j] + i <= m && Slab[Jump[j] + i] != 0)//如果到达了这次可以走到的地方没有超过M点,//并且这个位置已经来过,要取从起点到这个位置的步数和现在要更新的步数最少的Slab[Jump[j] + i] = min(Slab[Jump[j] + i], Slab[i]+1);else if(Jump[j] + i <= m)///将可以走的位置更新,由于是在i位置开始走的下一步,//所以走到这里的步数在i位置的基础上加一Slab[Jump[j] + i] = Slab[i]+1;}}if(0 == Slab[m])return -1;elsereturn Slab[m] -= 1;
}int main()
{int n,m;cin >> n >> m;cout << Jump_Slab(n,m) << endl;return 0;
}