动态规划是一种用来解决一类最优化问题的算法思想。简单来说,动态规划将一个复杂问题分解成若干个子问题,通过综合子问题的最优解来得到原问题的最优解。需要注意的是,动态规划会将每个求解过的子问题的解记录下来,以保证下一次遇到同样的子问题时,不会重复计算。
首先学会记录子问题的解,避免下次遇到同样的子问题时的重复计算。
以斐波那契数列为例子F0 = 1,F1 = 1, Fn = Fn-1 + Fn-2 (n>=2).初学者用递归是这样写的。
int F(int n)
{
if(n==0||n==1)
return 1;
else
return F(n-1)+F(n-2);
}
然而事实上这个递归会涉及到很多的重复操作,比如n==5时,F(5)=F(4)+F(3)而算F(4)时,又会F(4)=F(3)+F(2),F(3)就计算了2次。如果n非常大的时候,重复操作更是难以想象。
于是,我们开一个一维数组用来保存以及计算过的结果,其中dp[n]记录F(n)的结果,并用dp[n]=-1表示F(n)还未被计算过。
int dp[max];
int F(int n)
{
if(n==0||n==1)
return 1;
if(dp[n]!=-1)
return dp[n];
else
{
dp[n]=F(n-1)+F(n-2);
return dp[n];
}
}
这样的写法就大大降低了算法复杂度。重叠子问题:如果一个问题可以被分解为若干个子问题,且这些子问题会重复出现,那就称这个问题有重叠子问题。一个问题必须有重叠子问题才能使用动态规划。