递归的几个应用
递归的几个应用
SmartSage一、引入
通过最大子段和、简单装载问题、0/1背包问题这三个问题,加深对递归应用的理解。
二、最大子段和
给出一段序列,求这个序列的最大子段和。
比如-2,11,-4,13,-5,-2
最大的子段和就是11,-4,13
这个序列的和,是20;
我们采用分治的思想来解决这个问题。
如果将一个序列分成两部分,那么这个序列的最大子序列所在位置有三种情况:
1.在左侧序列中。
2.在右侧序列中。
3.横跨两个序列,一部分在左侧序列,一部分在右侧序列。
根据这三种情况,我们可以求得左侧序列最大的和,右侧序列最大的和,以及横跨两部分的最大的和,在比较这三者便可以得出最大的和。
对于左侧或者右侧序列的最大的和,我们可以再将他分为两部分,再去求,即,分治的思想。
对于横跨两部分的最大的和,我们可以从中间分别向两边累加求和,取和的最大值即可。
1 | int maxsubsum(int l, int r) |
时间复杂度为O(nlogn)
三、简单装载问题
题目:
有n个集装箱要装上一艘载重量为W的轮船,其中集装箱i(1≤i≤n)的重量为wi。不考虑集装箱的体积限制,现要这些集装箱中选出若干装上轮船,使它们的重量之和等于W,当总重量相同时要求选取的集装箱个数尽可能少。
可以遍历这些集装箱,对于集装箱i,有两种处理情况,分别是选和不选。这样就会得到一个二叉树的解结构。
在递归求解的过程中可以剪枝,比如,如果当前集装箱不选,剩下的集装箱重量和不足W,那么这个集装箱是必须要选的。如果选择当前的集装箱,重量超过了W,那么这个集装箱是一定不可以选的。
举一个例子,五个集装箱,重量分别为5,2,6,4,3,要求中重量达到10。
1 | void dfs(int num, int tw, int rw, int op[], int i) // num代表已经选择的集装箱个数,tw已选总总量,rw剩余重量,i考虑第i个集装箱 |
四、01背包问题
给定一载重量为W的背包及n个重量为wi、价值为vi的物体,1≤i≤n,要求而且重量和恰好为W具有最大的价值。这个与上面的简单装载问题差不多,只不过是条件变了变,也是逐一考虑每个物品,有两种情况,选择与不选
1 | void dfs(int i, int tw, int tv, int rw, int op[]) // i考虑第i个物品,tw当前重量,tv当前价值,rw背包剩下的空间 |
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果