其他分享
首页 > 其他分享> > 动态规划之跳石板

动态规划之跳石板

作者:互联网

解法框架

待定

跳石板

在这里插入图片描述

动态规划——有很多解,但是要求最优的那一个。动态规划的核心思想就是已经解决的问题要能被后面所利用。

采用下面的思维导图,梳理以下过程。跳石板的时候每次能跳得距离只能是当前石板的编号的约数(除了1和本身)

下图中,已经把从4跳到24的所有可能情况列了出来(由于篇幅限制,所以像7,11等这种情况就忽略了),用一个数组step保存从4开始到达每个石板数字的步数,比如step[8]=3,表示从4跳到8需要三步(这里把自己跳到自己身上算作1次),在初始情况下,除了step[4]=1(step[4]设置为1)之外的所有数字,全部设为一个很大的数,表示不可到达(下面思维导图中,用恶魔头像表示)
在这里插入图片描述

在这里插入图片描述

首先从4开始,对于4来说,只有一个约数2,所以它只能跳到6,当它的来到6之前需要进行判断一是到达的石板编号是否已经超越了目标石板编号,二是到达的石板是否为max,即是否是不可到达。所以这里到达6之后,判断第二个条件,6它是一个不可到达的石板,那么我们就直接就step[6]=step[4]+1,表示只需一步

在这里插入图片描述
来到6之后,它有两个选择,分别可以到达8和9,所以按照上述步骤,继续更新
在这里插入图片描述
对于8也是如此,对于9也是一样

所以大家可以发现,位于同一层级其实就表示步数是相同的,在当前情况下,走哪一条都可以
在这里插入图片描述
对于10,当他来到12时,此时由于之前8已经将12给更新了,所以从10到达12时,进行判断时m,12不是不可到达的一个石板,而是有确定的编号的,即step[12]=4,因此10在更新12时要进行一个比较:step[10+2]小还是step[10]+1小,很明显这里step[10+2]=step[12]=4<step[10]+1=4+1<5,因此step[12]继续保持为4,同时由10到12再到24这一条路线其实已经就pass了

接下来的过程就是重复上述过程了
在这里插入图片描述

代码

首先写出基本框架

#include <iostream>
#include <vector>
#include <math.h>
#include <limits.h>
using namespace std;

int Jump(int N,int M)
{
    return 0;
    
}

int main()
{
    int N,M;//起始石板编号和终止石板编号
    cin>>N>>M;
    cout<<Jump(N,M)<<endl;
    
    
}

第二步编写Jump函数

#include <iostream>
#include <vector>
#include <math.h>
#include <limits.h>
using namespace std;

void getdiv(int n,vector<int>& div)
{
    for(int i=2;i<=sqrt(n);i++)
    {
       if(n%i==0)
       {
           div.push_back(i);
           if((n/i)!=i)//非平方数注意不要忽略
               div.push_back(n/i);
       }
    }
}

int Jump(int N,int M)
{
    vector<int> step(M+1,INT_MAX);//放置越界,初始化M+1大小
    step[N]=1;//自己跳到自己算1步,其实这里为0也可以,最后反悔的时候不用减1即可
    
    for(int i=N;i<M;i++)
    {
        if(step[i]==INT_MAX)//这个点不可达,continue
            continue;
        
        vector<int> div;//用于获取i的约数
        getdiv(i,div);
        for(int j=0;j<div.size();j++)//动态规划核心代码
        {
            if((div[j]+i)<=M && step[i+div[j]]!=INT_MAX)
            //i+div[j]这个石板不等于INT_MAX,表示肯定已经走过了而且保存的是最小值
            {
                step[i+div[j]]=min(step[i+div[j]],step[i]+1);
                
            }
            else if((div[j]+i)<=M)//不可达
                step[i+div[j]]=step[i]+1;
            
        }
    }
    if(step[M]==INT_MAX)
    {
        return -1;
    }
    else
        return step[M]-1;//起始位置是1开始的
}

int main()
{
    int N,M;//起始石板编号和终止石板编号
    cin>>N>>M;
    cout<<Jump(N,M)<<endl;
    
    
}

在这里插入图片描述

标签:12,石板,int,include,step,div,动态,规划
来源: https://blog.csdn.net/qq_39183034/article/details/116736980