递归与动态规划解题策略:Fibonacci数与最长有序子序列

需积分: 9 0 下载量 150 浏览量 更新于2024-08-24 收藏 1.66MB PPT 举报
"递归程序实现与动态规划在ACM程序设计中的应用" 在ACM程序设计中,递归是一种常见的解决问题的方法,特别是在处理数学问题和算法时。递归程序通常简洁明了,但如果不加以优化,可能会导致性能问题。以Fibonacci数列为例,给出的递归实现如下: ```cpp int fa(int n) { if(n == 1 || n == 2) return 1; else return fa(n-1) + fa(n-2); } ``` 这段代码中存在一个问题,即重复计算。当计算较大的Fibonacci数时,如`fa(n)`,会重复计算`fa(n-1)`和`fa(n-2)`,这导致效率极低,因为同一个子问题会被反复解决。为了解决这个问题,我们可以采用动态规划的方法。 动态规划是一种将问题分解为更小的子问题,并存储已解决子问题的结果,避免重复计算的技术。对于Fibonacci数列,可以使用数组来存储已计算过的值,避免重复计算: ```cpp int a[100] = {0}; int fa(int n) { if(a[n] != 0) return a[n]; if(n == 1 || n == 2) { a[n] = 1; return a[n]; } else { a[n] = fa(n-1) + fa(n-2); return a[n]; } } ``` 这种方法提高了程序的效率,因为它利用数组`a`存储了之前计算过的Fibonacci数,避免了重复调用。 接下来,我们看一个思考题:最长有序子序列。给定一个序列,我们需要找到其中最长的非降序子序列的长度。可以使用动态规划`F[I]`来记录以每个位置为结尾的最长有序子序列长度。例如: ```cpp I Num[I] F[I] 0 1 1 1 4 2 2 7 3 3 2 2 4 5 3 5 8 4 6 3 3 7 6 4 8 9 5 ``` 这里的`F[I]`表示以`Num[I]`为结尾的最长有序子序列的长度。 另一个思考题是寻找具有特定条件的大象序列的最长子序列,这里同样运用动态规划的思想。设`f[i]`表示以`ele[i]`为结尾的符合条件的最长序列长度。通过对大象数组按照重量和智商排序,然后根据动态规划的公式更新`f[i]`。 最后,提到的最大子段和问题,要求在一个整数序列中找到连续子段的最大和。这个问题可以使用Kadane's algorithm解决,它通过遍历序列,记录当前子段和与全局最大子段和,从而找到最大子段和。 递归和动态规划在ACM程序设计中扮演着重要的角色。递归提供了一种直观的解决问题方式,而动态规划则通过优化递归,避免重复计算,提高了算法效率。这两个概念在解决复杂问题时相辅相成,是算法设计和分析的关键工具。