Fibi 指的是书中使用循环实现的斐波那契数列代码,如下:
longFibi(int n){// Fibi(46) is largest value that fits in a longAssert((n >0)&&(n <47),"Input out of range");long past, prev, curr;
past = prev = curr =1;for(int i =3; i <= n; i++){
past = prev;// past holds Fibi(n-2)
prev = curr;// prev holds Fibi(n-1)
curr = past + prev;// curr holds Fibi(n)}return curr;}
友情链接:(转)《剑指offer》中的斐波那契数列系列问题
01背包问题中每种物品只有1个,物品只有两种状态,要么在背包内,要么不在背包内。
先给出状态转移方程,之后进行分析: P[i][j]=max(P[i−1][j],P[i−1][j−Vol[i]]+Value[i])
其中,i 表示第 i 个物体,j 表示背包的容量,Vol[i]表示第 i 个物体的体积, Value[i] 表示第 i 个物体的价值。
P[i][j] 表示对于容量为 j 的背包来说,前 i 件物体放置可以得到的最大价值。(重要)
2.1.1 分析
正如我们在引言中提到动态规划的概念,在搜索空间中搜索最优解的过程中,我们将问题划分成一个个子问题,我们会不断地尝试、计算、回退,重复计算的开销很大,所以我们需要保存中间结果,这就是我们使用矩阵 P[i][j] 的原因。
那么怎么决定每一个子问题最优解 P[i][j] 的取值呢?状态转移方程是怎么得到的呢?
举个例子,求容量为 10 的背包的最佳放置方案。
假如我们已经决定了前 i−1 件物品的最优方案,得到了 P[i−1][10] 的取值,这个值可能是 100(随便假设的),接下来我们要考虑第 i 件物品了,第 i 件物品的价值是 2(也是随便假设的)。
若第 i 个物体在背包里,P[i][10] 的取值肯定不小于 P[i−1][10],为什么?因为如果将第 i 件物品放进入背包,但取值反而减小了,说明有一些物品为了给物品 i 腾位置被拿出来了。这才会导致取值不增反减,也会使得我们的假设不成立。
所以,我们需要考察放入物品 i 后的取值能否大于 P[i−1][10],否则就没有更新的必要了。
我们希望放入物品 i 后的方案是最优的,不妨这样考虑:第 i 个物体我们已经假设在背包里了,那么我们留下的空间只有 10−Vol[i],若能找到这 10−Vol[i] 的空间的最优值,在这个最优值的基础上加上物品 i 的价值,不就是我们想要考察的P[i][10] 的最优取值吗?(当然,是不是最优还要和 P[i−1][10] 比较一番~)
而我们的矩阵正是保存着这样的最优值,注意到这 10−Vol[i] 的空间只能留给前 i−1 个物体,也就是说我们实际上考察的是 (P[i−1][10−Vol[i]]+Value[i]) 的取值能不能大于 P[i−1][10]。
假如我们运气好,找到的 P[i−1][10−Vol[i]] 为99,那么毫无疑问,P[i][10] 可以更新为 99+2=101 了。
将我们的例子泛化为一般形式就能得到状态转移方程了。