动态规划-重叠子问题
flyfish 2015-8-23
名词解释
重叠子问题 overlapping subproblems
动态规划策略将问题分解为一个或者多个子问题
重叠子问题是一个递归解决方案里包含的子问题虽然很多,但不同子问题很少。少量的子问题被重复解决很多次。
例如LCS(最长公共子序列)问题,给定两个序列X和Y,长度分别是m和n,穷举子问题是指数级的,而不同子问题的数量只是mn.
a recurisive algorithn for the problem solves the same subproblems over and over,rather than always generating new subproblems.
用来解原问题的递归算法可以反复地解同样的子问题,而不是总在产生新的子问题。
over and over 反复,再三
rather than 而不是;宁可…也不愿
When a recursive algorithm revisits the same problems repeatedly,we say that the optimization problem has overlapping subproblems.
当一个递归算法不断地调用同一问题时,我们说该最优问题包含重叠子问题
revisit 英 [riː’vɪzɪt] 美 [ri’vɪzɪt]
vt. 重游;再访;重临
n. 再访问
repeatedly 英 [rɪ’piːtɪdlɪ] 美 [rɪ’pitɪdli]
adv. 反复地;再三地;屡次地
In contrast, a problem for which a divide-and-conquer approach is suitalbe usually generates brand-new problems at each step of the recursion.
相反地,适用于分治法解决问题往往在递归的每一个步上都产生全新的问题。
contrast英 [‘kɒntrɑːst] 美 [‘kɑntræst]
vi. 对比;形成对照
vt. 使对比;使与…对照
n. 对比;差别;对照物
divide-and-conquer
分治法
approach 英 [ə’prəʊtʃ] 美 [ə’protʃ]
n. 方法;途径;接近
vt. 接近;着手处理
vi. 靠近
suitable 英 [‘suːtəb(ə)l] 美 [‘sutəbl]
adj. 适当的;相配的
brand-new
adj. 崭新的;最近获得的
brand 英 [brænd] 美 [brænd]
vt. 铭刻于,铭记;打烙印于;印…商标于
n. 商标,牌子;烙印
以斐波那契数列为例说明
斐波那契数列指的是这样一个数列:1、1、2、3、5、8、13
从第3个数开始,每个数都是前面两个数之和。
测试时 输入的 n>=3,但也不要太大,防止溢出。
递归式
Consider again the recursive function for computing the nth Fibonacii number
.
再次考虑使用递归函数计算第n个斐波那契数。
int Fibonacci(int n)
{
if( (1==n) || (2==n) )
return 1;
return Fibonacci(n-1) + Fibonacci(n-2);
}
调用 Fibonacci(7);
存表方式
动态规划算法总是充分利用重叠子问题,即通过每个子问题只解一次,把解保存在一个需要时就可以查看的表中,而每次查表的时间为常数。
Dynamic-programming algorithms typically take advantage of overlapping subproblems by solving each subproblem once and then storing the solution in a table where it can be looked up when needed, using constant time per lookup.
typically 英 [‘tɪpɪkəlɪ] 美 [‘tɪpɪkli]
adv. 代表性地;作为特色地,典型地
take advantage of
利用
int Fibonacci(int n,int* Values)
{
if(n<=2)
return 1;
Values[n]=Fibonacci(n-1,Values) + Fibonacci(n-2,Values);
return Values[n];
}
调用
int Values[8]={0,0,0,0,0,0,0,0};
Fibonacci(7,Values);
不需要表存储所有值,只存储前两个值
int Fibonacci(int n)
{
long past,prev,curr;
past=prev=curr=1;
for(int i=3;i<=n;i++)
{
past=prev; // past holds Fibonacci(i-2)
prev=curr; // past holds Fibonacci(i-1)
curr=past+prev; // current now Fibonacciholds (i)
}
return curr;
}
调用 Fibonacci(7);