网易跳石板问题详解

基本思想:DP算法
首先创建一个最大值+1那么大的数组表示每一个石板,之所以是最大值+1的原因是要取下标为最大值的石板
然后遍历每个石板,把每个石板的约数都保存起来,然后取到从这个石板过去的最小值(即最优解)
然后取最大值对应的那个石板返回就OK
DP算法的核心思维其实就是每一步取最优解,它也是一种分治思想的深刻体现

#include
#include
#include
using namespace std;
void GainStep(int n, vector& arr)
{
//for (int i = 2; i < n; i++)
//{
// if (n % i == 0)
// {
// arr.push_back(i);
//}
//}
//这样子的话因为算法复杂度太大过不了,所以我们简化一下
//因为一个数的约数不可能超过它的开方,所以只要遍历它开方前的数字,如果它是n的约数,那么把它和n/它的值扔进去就行
//当让遇到商和除数一样的扔一个就行比如4=2*2扔一个2就行
for (int i = 2; i <= sqrt(n); i++)
{
if (n % i == 0)
{
arr.push_back(i);
//判断一手n/i是否是不是i如果不是把n/i扔进去
if (n / i != i)
{
arr.push_back(n / i);
}
}
}
}
void getMinRoute(int n, int m)
{
vectordp(m + 1, 0); //台阶数
dp[n] = 1;
for (int i = n; i < m + 1; ++i) //当前是哪个台阶
{
vectorarr;//建立一个打工仔去装当前台阶所能跳跃的阶数(当前台阶的约数)
if (dp[i] == 0)//表示当前台阶不可达,直接跳过
continue;
//首先获取当前台阶所能跳跃的步数
GainStep(i, arr);
for (int j = 0; j < arr.size(); ++j)//遍历所以可能跳跃过的步数
{
if (arr[j] + i <= m)//意味着可以跳,如果大于了,就没有跳的必要了
{
//判断一手当前这一步是不是已经跳过了
if (dp[arr[j] + i] != 0)
{
dp[arr[j] + i] = min(dp[arr[j] + i], dp[i] + 1);
//这里的dp[i]+1的意义是从你这到下一步,相当于走了一步
//所以给你+1就是下一步的步数,比如你是第二步,那么你的下一步就是第三步
}
//如果没人跳过,那没得商量直接走
else
{
dp[arr[j] + i] = dp[i] + 1;
}
}
}
}
//取出dp里边最后一步的值即可,当然,如果它没有被走过,那么它的值势必为0,直接输出-1就ok
if (dp[m] == 0)
cout << “-1” << endl;
else
{
cout << dp[m] - 1 << endl; //-1的原因是我们是从1开始计数的,因此我们事实上多记了一步
}
}
int main()
{
int m, n;
while (cin >> n >> m)
getMinRoute(n, m);
return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值