算法笔记——动态规划法

动态规划法常常适用于有重叠子问题和最优子结构性质的问题,在重复子问题的数目关于输入的规模呈指数增长时特别有用。
动态规划法的本质其实就是试图仅仅解决每个子问题一次,具有天然剪枝的功能,从而减少计算量:一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。即每个问题只管好他的子问题呈现的结果,而至于它是怎么来的则全然不管。重点是查表,表的设计决定着算法的好坏。
最经典的爬楼梯问题,每次只能爬一层或两层,问爬到第n层有多少个不同的方案?
你会发现用函数递归,或者回溯法的代码提交都会超时(在正式的算法考试中不会告诉你超时的),这样你只能得到一部分分数,下面介绍动态规划法是如何降低复杂度的
爬楼梯:
int n=reader.nextInt();
int[] test=new int[n];
test[0]=1;
test[1]=2;
for(int i=2;i test[i]=test[i-1]+test[i-2];
}
System.out.println(test[n-1]);

在求解test[i]时,等同于求test[i-1]和test[i-2],再求test[i+1]时可由刚刚存储在数组中的值直接求出,
我们不用关心之前存储的值是怎样来的,也不用再计算一遍,这样可大大节省时间。
而在递归法中,在求解test(i)时,等同于求test(i-1)和test(i-2),由于我们没有记录它们的值,在计算
test(i+1)时,依然需要再算一遍test(i)和test(i-1)。
所以说动态规划法是用空间换时间,在多数时候,这种交换是比较值得的。

下面是一道质量比较好的算法题:
试问正整数n最少有几个完全平方数构成?

算法笔记——动态规划法_第1张图片
最坏的情况,比如3,只能由3个1组成,但是4,可以由4组成。
对于要计算的dp[i],可能最后加的完全平方数是1、4、9……,
那么分别是在dp[i-1]+1、dp[i-4]+1等中找最小值,这样就可以计算出i最少由几个完全平方数组成,
为之后的计算也提供了一种选择,即某个数k:dp[k]=dp[i]+1(k-i是完全平方数),即k由两部分组成,一是k-i,二是i,k-i是一个平方数,i是dp[i]个平方数。

明天会继续写几道动态规划法的题。

你可能感兴趣的:(算法,动态规划法)