迭代解决方案作为动态编程
iterative solution as dynamic programming
wikipedia对动态编程说:
在数学,计算机科学,经济学和生物信息学中,动态编程是一种通过将其分解为简单的子问题集来解决复杂问题的方法。它适用于表现出重叠子问题和最佳子结构的特性的问题。如果适用,该方法比其他不利用子问题重叠的方法所花费的时间要少得多(例如Depth-Inst搜索)。
以及从Introduction to Algorithms (Cormen)
中,我了解到dynamic programming
是一种应用于求解具有already been computed once
的repeating computations
的方法。用外行的话来说,
如果您要一次又一次地计算某些东西,最好将其存储在某个地方。
将其应用于fibonacci 我可以写下其算法如下:
arr[3] = {1,1,1} //first two index for computation , last to keep track
fibbDyn(n){
if(n>=1 || a[2]>n ) return n; // return on base conditions
else {
res = arr[0] + fibbDyn(n-1);
arr[0]=arr[1];
arr[1]=res;
arr[2]+=1; // increment value by 1
return res;
}
}
我相信该算法遵循动态编程的示例,因为它减少了在>原始递归fibbonaci 版本中所做的额外计算:
fibb(n){
if (n>=1)return n;
else return fibb(n-1) + fibb(n-2);
}
由于在每个递归步骤else return fibb(n-1) + fibb(n-2)
上有两个单独的呼叫,因此重复了许多计算。
迭代解决方案可能看起来像:
int FibonacciIterative(int n)
{
if (n == 0) return 0;
if (n == 1) return 1;
int prevPrev = 0;
int prev = 1;
int result = 0;
for (int i = 2; i <= n; i++)
{
result = prev + prevPrev;
prevPrev = prev;
prev = result;
}
return result;
}
所以我的问题是,fibonacci问题的迭代解决方案是否被归类为动态编程?
我分歧的原因是,迭代解决方案没有表现出诸如递归解决方案之类的Overlapping subproblems
。在迭代解决方案中,没有进行冗余和重复的计算,因此不应包含在动态编程中。
相关文章:最佳子结构,重叠的子问题,动态编程。
是。这只是自下而上的动态编程的特殊情况。如果您只需要保留2个条目,那么您就可以丢弃您知道永远不会再使用的表条目,这意味着您只需要保留2个条目,然后您就可以忘记它是一个桌子,只需使用两个命名变量即可。因此,最终看起来与众不同,几乎太简单了。但是该算法的结构仍然是DP。您说的不存在的重叠子问题仍然存在,因为您两次使用每一个结果(在prev
中,一次是在prevPrev
中再次使用),除了最后。当然,没有进行冗余计算,但这就是DP的想法 - 通过重复使用删除冗余计算。
有一个通用的"攻击计划",用于允许动态编程的问题,即
- 递归地陈述问题
- (证明可以应用DP)
- 确定子问题的排序以使它们在拓扑上进行分类(因此,计算解决方案仅依赖于琐碎的解决方案和以前计算的解决方案,而不是未来的解决方案)
- 如果有一个不错的顺序,则以该顺序迭代地填充表。如果订单很烦人,也许保持自上而下的结构。
在斐波那契,发生的事情是订单很琐碎(这甚至不是特别罕见,但它看起来好像我们"并没有真正做任何特别的事情"),而依赖关系再也不会回头了比2个位置,因此表的唯一部分要记住的是前两个单元格。因此,应用所有这些,您会得到众所周知的迭代算法。这并不意味着它不再是DP,这意味着DP非常成功。
至于属性(最佳子结构,重叠的子问题),它们是问题的属性的属性,无论您如何决定解决它,它们都不会消失。但是您仍然可以在迭代算法中看到它们,正如我在第一段中指出的那样。
在动态编程的Wikipedia页面上读取 - 计算机编程中的动态编程。这解释了这两种方法,上面是作为问题的递归表述而掉落的,并且可以迭代地生成对更大问题的解决方案,并将当前解决方案存储在表中。在这种情况下,不需要表,可以使用两个变量完成工作。因此,在迭代方法的情况下,只有两个变量用于保持子问题的值。即prev, (i-1 th)
和prevPrev, (i-2 th)
。在这里,使用prevPrev来找到迭代的解决方案(更大的问题)。
result = prev + prevPrev;
不过是ITH迭代结果的表示,它等于Prev(i-1) PrevPrev(i-2)。因此,在迭代方法中也发生了子问题的重复使用。这是动态编程的自下而上的方法,递归方法是动态编程的自上而下的方法。
- 此动态编程问题的自上而下方法
- 使用动态编程以有限的资金选择活动
- 寻找解决这个动态编程问题的提示
- 为什么其中一个斐波那契序列的动态编程实现比另一个更快
- 不明白为什么动态编程在这里不起作用
- 如何在动态编程中选择缓存的初始值?
- 使用动态编程解决的 C++ 平台
- C :动态编程,给定3个可能的操作
- 使用动态编程计算二项式系数
- C++中TSP的动态编程解决方案
- 动态编程中这种初始化背后的直觉
- 葡萄酒选择动态编程
- 双递归动态编程
- 带1D阵列USACO培训的动态编程:子集总和
- 如何将3个数字映射到值(动态编程)
- 用于字符串比较的动态编程
- 带有动态编程的C 中的UVA 3N 1
- 计算5*n板的正确配置(动态编程,C++)
- 需要建议,以提高单词中断速度(动态编程)
- 迭代解决方案作为动态编程