当前位置:首页 > 牛客 > 牛客12576题解题全解析:动态规划+质因数分解实现跳跃问题最优解

牛客12576题解题全解析:动态规划+质因数分解实现跳跃问题最优解

3个月前 (06-10)

牛客12576题解题全解析:动态规划+质因数分解实现跳跃问题最优解 动态规划 质因数分解  代码优化 第1张


一、题目解读

牛客12576题是一道经典的算法题,要求给定起点N和终点M,求解从N到M的最少跳跃次数。题目考察的核心在于路径优化与动态规划思想,需结合数论中的质因数分解技巧,通过合理设计算法降低时间复杂度,避免暴力枚举的指数级耗时。

二、解题思路

采用“动态规划+质因数分解”的双重优化策略。首先,通过质因数分解函数getJumps()高效获取每个数的跳跃因子(即质因数),避免对非质因数位置的无效计算。随后,利用动态规划数组dp[]记录各节点的最小跳跃次数,从起点N递推至终点M,通过状态转移方程dp[i+jump] = min(dp[i+jump], dp[i]+1)实现路径优化。特别处理了N=M的边界情况,以及跳跃超出范围时的剪枝,确保代码高效且逻辑严谨。

三、解题步骤详解

    1. 预处理质因数:调用getJumps()函数,通过筛选法仅对平方数以内的候选数进行试除,若找到质因数i及其对应的补数n/i(当i≠n/i时),则将其加入跳跃列表。

    2. 初始化动态规划:创建dp数组,初始值设为INT_MAX,表示未访问状态。起点N赋值为0,作为递推基准。

    3. 递推更新路径:从N开始正向迭代,仅对已计算的最小步数节点(dp[i]≠INT_MAX)扩展。遍历该节点的跳跃列表,计算可达位置i+jump,若未超界则更新dp值。

    4. 输出结果:最终判断dp[M]是否可达,若为INT_MAX则输出-1,否则输出最小步数。

四、代码及注释

#include <iostream>
#include <vector>
#include <climits>
#include <algorithm>
using namespace std;

// 质因数分解函数:获取数n的所有跳跃因子(质因数)
vector<int> getJumps(int n) {
   vector<int> res;
   if(n <= 1) return res; // 边界处理:1及以下无需分解
   for(int i=2; i*i<=n; ++i) { // 优化:仅遍历至√n
       if(n%i == 0) { // 若i是质因数
           res.push_back(i);
           if(i!= n/i) res.push_back(n/i); // 补数非自身时加入(避免重复)
       }
   }
   return res;
}

int main() {
   int N, M; // 输入起点和终点
   cin >> N >> M;
   if(N == M) { // 边界特判:起点=终点无需跳跃
       cout << 0 << endl;
       return 0;
   }
   
   vector<int> dp(M+1, INT_MAX); // 动态规划数组,初始化为最大值
   dp[N] = 0; // 起点步数为0

   for(int i=N; i<=M; ++i) { // 正向迭代扩展
       if(dp[i] == INT_MAX) continue; // 跳过未访问节点
       vector<int> jumps = getJumps(i); // 获取当前节点的跳跃列表
       for(int jump : jumps) { // 遍历跳跃因子
           if(i + jump > M) continue; // 剪枝:超出终点范围不更新
           dp[i+jump] = min(dp[i+jump], dp[i]+1); // 状态转移:更新最小步数
       }
   }
   
   cout << (dp[M]==INT_MAX? -1 : dp[M]) << endl; // 输出结果或不可达标记
   return 0;
}

五、总结

该解法巧妙结合质因数分解与动态规划,将跳跃问题的路径搜索转化为局部最优解的递推。通过精确计算跳跃因子与剪枝优化,避免了传统广度优先搜索的冗余计算,时间复杂度降至O(√n * (M-N)),空间复杂度为O(M)。适用于求解中小规模范围内的最短路跳跃问题,为同类算法优化提供了数论与动态规划结合的典型范例。

原创内容 转载请注明出处

分享给朋友:

相关文章

力扣70题:告别暴力递归!从零实现记忆化搜索解法

力扣70题:告别暴力递归!从零实现记忆化搜索解法

题意解析:想象你站在楼梯底部,面前有n级台阶。每次你可以选择跨1级或2级台阶,最终到达顶端的路径有多少种不同的走法?这个问题本质上是在探索分叉决策的叠加效果——当我们把每个台阶处的选择看作二叉树的分支...

力扣198.打家劫舍|动态规划解法中的特殊边界处理

力扣198.打家劫舍|动态规划解法中的特殊边界处理

题意解析:在排列成直线的房屋群中,每个房屋藏有价值不同的财物。小偷不能连续抢劫相邻的两间房屋,否则会触发警报。我们需要设计一套抢劫策略,使得在不触发警报的前提下,能够获取的最大财物总和。这个问题本质上...

力扣1137题:动态规划解泰波那契数 高效求解第N项的秘密

力扣1137题:动态规划解泰波那契数 高效求解第N项的秘密

一:重新解读题目泰波那契数列是一个充满数学趣味的递推序列:从第3项开始,每个数均为前三个数的和(即Tₙ₊₃ = Tₙ + Tₙ₊₁ + Tₙ₊₂)。当给定整数n时,需要高效计算出第n项的值。面对此类递...

牛客DP41精讲:当背包必须装满时,你的状态转移方程该如何调整?

牛客DP41精讲:当背包必须装满时,你的状态转移方程该如何调整?

题目重解我们面对一个经典背包问题的变体:给定n个物品,每个物品有重量w和价值v,背包容量为V。需要回答两个问题:1) 普通情况下能获得的最大价值;2) 必须恰好装满背包时的最大价值(若无法装满则输出0...

GESP2023年六级真题解析:动态规划解决小杨买饮料问题(洛谷3873)

GESP2023年六级真题解析:动态规划解决小杨买饮料问题(洛谷3873)

一、题目解读小杨买饮料是GESP 2023年六级认证考试中的一道经典动态规划题目,考察学生对背包问题的理解和应用能力。题目描述小杨需要购买n种饮料,每种饮料有特定的体积w和价格v,他要在不超过容量l的...

NOIP 2008火柴棒等式题解(C++代码实现)  动态规划与枚举算法详解

NOIP 2008火柴棒等式题解(C++代码实现) 动态规划与枚举算法详解

一、题目解读火柴棒等式问题(NOIP 2008,洛谷P1149)要求使用给定数量的火柴棒,构造形如 A + B = C 的等式,其中A、B、C均为整数,且火柴棒总数恰好等于输入值。需统计符合条件的等式...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。