今日事项-2024年7月18日
今日事项-2024年7月18日
事项一 看3个实用的算法
1. 单源最短路径(Bellman-Ford Algorithm)

产生原因与背景:
想象你是一名邮递员,需要从邮局出发,递送包裹到城市中的各个角落。单源最短路径算法就像你规划的路线,它帮助你找到从邮局到每个目的地的最短路径,即使有些道路可能会因为修路而暂时封闭。
算法思路:
单源最短路径算法就像是一位旅行者在探索一个未知的岛屿,他从起点出发,逐步探索每一条可能的路径,直到确定没有更短的路径可以到达目的地。
代码案列:
1 | |
算法优缺点:
优点:Bellman-Ford算法能够处理图中的负权边,并且能够检测负权环。
缺点:算法的时间复杂度为O(|V| * |E|),在|E|接近|V|^2的稠密图中效率较低。
解决缺点的方法:
对于不包含负权边的图,可以使用更高效的算法,如Dijkstra算法。
解决缺点后的代码案例:
略(Dijkstra算法已经在上文中给出)
算法的3个实际应用案例:
- 路网导航:在存在临时道路施工或通行费变更的情况下,计算最短路径。
- 金融分析:在金融市场中,评估不同投资组合的风险和回报。
- 供应链优化:在存在多种运输成本和时间的情况下,找到成本最低的运输路径。
2. 长路径问题(Longest Path Problem)
产生原因与背景:
想象你是一名探险家,正在探索一个未知的森林,你需要找到一条最长的路径,以便尽可能多地探索森林的每一个角落。长路径问题就像你的探险地图,帮你找到森林中最长的路径。
算法思路:
长路径问题就像是一位旅行者在规划他的旅程,他需要考虑所有可能的路线,并选择一条能够覆盖最远距离的路线。
代码案列:
略(长路径问题的实现较为复杂,通常涉及图的遍历)
算法优缺点:
优点:长路径问题在某些应用中非常有用,如在网络设计中找到最长的通信路径。
缺点:长路径问题在某些图中可能非常难以解决,特别是图中存在很多环和交叉路径时。
解决缺点的方法:
可以通过使用动态规划或图的拓扑排序来解决长路径问题,这些方法可以避免在环中无限循环。
解决缺点后的代码案例:
略(实现通常需要特定的图结构和算法)
算法的3个实际应用案例:
- 网络设计:在设计通信网络时,找到最长的通信路径。
- 物流规划:在物流配送中,规划最长的配送路线以覆盖更多的客户。
- 游戏设计:在游戏关卡设计中,找到最长的探索路径以增加游戏的挑战性。
3. 斐波那契数列(Fibonacci Sequence)
斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)
产生原因与背景:
想象你是一名生物学家,正在研究兔子的繁殖问题。斐波那契数列描述了一对兔子每个月繁殖的后代数量,每个月新生的兔子下个月开始繁殖,直到无穷。
算法思路:
斐波那契数列就像是一位园丁在计算植物的生长,每一代植物的数量是前两代植物数量的和。
代码案列:
1 | |
算法优缺点:
优点:斐波那契数列的递归实现非常直观,易于理解。
缺点:递归实现在计算大的n时效率较低,因为有很多重复计算。
解决缺点的方法:
使用动态规划方法,通过存储已经计算过的斐波那契数来避免重复计算。
解决缺点后的代码案例:
1 | |
算法的3个实际应用案例:
- 计算机算法竞赛:在解决优化问题时,经常需要计算斐波那契数列。
- 金融数学:在某些金融模型中,斐波那契数列用于预测市场趋势。
- 生物信息学:在DNA序列分析中,斐波那契数列用于描述某些生物过程。
事项二 吃透 快速幂算法
通过一个具体的例子来演示这个快速幂算法的代码是如何工作的。假设我们要计算[2^{10}]。
代码:
1 | |
计算过程:
初始状态:
- ( a = 2 )
- ( b = 10 )
- ( result = 1 )
第一次循环:
- ( b = 10 )(二进制为1010)
- ( b & 1 = 0 )(不是奇数,不执行乘法)
- ( a = 2 * 2 = 4 )
- ( b = 10 )右移一位 = ( 5 )(二进制为101)
第二次循环:
- ( b = 5 )(二进制为101)
- ( b & 1 = 1 )(是奇数,执行乘法)
- ( result = 1 * 4 = 4 )
- ( a = 4 * 4 = 16 )
- ( b = 5 )右移一位 = ( 2 )(二进制为10)
第三次循环:
- ( b = 2 )(二进制为10)
- ( b & 1 = 0 )(不是奇数,不执行乘法)
- ( a = 16 * 16 = 256 )
- ( b = 2 )右移一位 = ( 1 )(二进制为1)
第四次循环:
- ( b = 1 )(二进制为1)
- ( b & 1 = 1 )(是奇数,执行乘法)
- ( result = 4 * 256 = 1024 )
- ( a = 256 * 256 )(这一步在循环结束后执行,不影响结果)
- ( b = 1 )右移一位 = ( 0 )(循环结束)
最终结果:
- ( result = 1024 ),这就是[2^{10}]的结果。
通过这种方式,快速幂算法有效地减少了乘法的次数,从而提高了计算的效率。
涉及到的知识点
这段代码中涉及到的语法知识点主要包括以下几点:
函数定义:
- 使用
def关键字定义函数。 - 函数名
Fast_Pow,参数列表(long long a, long long b)。
- 使用
数据类型:
long long:在C/C++中,long long是一种64位整数类型,用于存储大整数。
变量声明与初始化:
long long result = 1;:声明并初始化一个long long类型的变量result,初始值为1。
循环结构:
while (b):一个无限循环,条件是b非零。当b为零时,循环结束。
位运算:
b & 1:位与运算,用于判断b的最后一位是否为1,即判断b是否为奇数。b >>= 1:位右移运算,将b的二进制表示向右移动一位,相当于将b除以2。
条件判断:
if语句:用于条件判断。如果条件为真,则执行if块内的代码。
乘法运算:
result *= a;:乘法赋值运算符,相当于result = result * a;。
赋值运算:
a *= a;:赋值运算符,用于将a的平方赋值给a。
递归调用:
- 尽管这段代码本身不是递归实现的,但快速幂算法的递归实现会涉及递归调用,即函数调用自身。
返回值:
return result;:结束函数,并将结果返回给调用者。
注释:
- 使用
/*和*/进行多行注释,或者使用//进行单行注释。
- 使用
这些知识点是理解和实现快速幂算法的基础,也是C/C++编程中常用的语法和概念。