头疼的动态规划:跳木板

题目: 

小易来到了一条石板路前,每块石板上从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

题解:

题目十分简单易懂,我们只需要每次跳跃n的约数步即可。但是约数步又不能只能是最大公约数步,如果是最大公约数步大部分样例行不通。就拿上面的样例来说4->6->9->12->18->27这样就行不通。因此我们需要将公约数全部求取一遍!此时,我就有点进自己的思维坑了。全部求取,哦哦哦哦哦,这不就是那个什么嘛?   

什么?回溯算法吖。

来,上代码:

#include<iostream>
#include<vector>
#include<algorithm>
#include <climits>
using namespace std;
void Stoneslab(int n,int m,int& ret,int gap)
{
    if(n>m)
        return;
    if(n==m)//相等的话,符合要求,计算最小步骤和
    {
        ret=min(ret,gap);
        return ;
    }
    for(int i=2;i<=sqrt(n);++i)
    {
        if(n%i==0)//i是n的约数,进入回溯算法
        {
            if(n+i<=m)
                Stoneslab(n+i,m,ret,gap+1);
            if(n+n/i<=m)
                Stoneslab(n+n/i,m,ret,gap+1);
            
        }

    }
}
int main()
{
    int n,m;
    cin>>n>>m;
    int ret=INT_MAX;
    int gap=0;
    Stoneslab(n,m,ret,gap);
    if(ret==INT_MAX)
        cout<<-1<<endl;
    else
        cout<<ret<<endl;
    
    return 0;
}

写完之后,感觉没什么嘛?一点运行,唉!奈何太复杂。

只能通过50%,如果n和m相差过大,决策树太过庞大,导致用时过高。

新思路:

还有什么想法呢?我这只菜鸡,只能翻翻题解,看看!找到以下差不多的动态规划!这思路太强了!

来,代码中弄题解!

#include<iostream>
#include<vector>
#include<algorithm>
#include <climits>
using namespace std;
int main()
{
	int n, m;
	cin >> n >> m;
	//将0~m的位置初始化为给定值
	vector<int> arr(m + 1, INT_MAX);
	//将n的这个位置进行差异化
	arr[n] = 0;
	for (int i = 0; i<m + 1; ++i)
	{
		if (arr[i] == INT_MAX)
			continue;
         //当第一次进入下面的代码是从N开始
		for (int j = 2; j <= sqrt(i); ++j)
		{
			if (i%j == 0)//j是当前值的非1非本身的约数
			{
                //将N+约数位置改变为次数,遍历到的时候进入此处循环
				if (i + j <= m)
					arr[i + j] = min(arr[i] + 1, arr[i + j]);
				if (i + i / j <= m)
					arr[i + i / j] = min(arr[i] + 1, arr[i + i / j]);

			}

		}


	}
	if (arr[m] == INT_MAX)
		cout << -1 << endl;
	else
		cout << arr[m] << endl;

	return 0;
}

 

给小伙伴的话: 

最近几天,怎么说呢?有点无故偷工!不太想搞代码。毕竟,每天要瞅七八个小时有时候是十几个小时电脑,实在是oh myGod!眼睛实在是休息不过来,不过还好,有人观看我的博客算是我学习中的一大动力!我会调节好自己的节奏,每天坚持下来,直到我能拿到offer吧! 我也希望看到这里的小伙伴能保护好自己的眼睛!

 

本篇博文到这里就结束了,谢谢大家的观看!

你们的 【三连】 是给Qyuan最大的肯定!

↓          ↓           ↓

注:如果本篇博客有任何错误和建议,欢迎伙伴们留言,你快说句话啊!

如果需要练习的小伙伴,可以打开下方链接:

链接:https://www.nowcoder.com/questionTerminal/4284c8f466814870bae7799a07d49ec8 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值