说到动态规划就不得不提一下分治法。因为动态规划是分支法的提升和优化。
分治法中,在分支法中我们通常将问题分解成n个互相独立的的大致一样的子问题,通过求解子问题的解,来获得原问题的解。
但是它有一个弊端。举例说明:(斐波那契数列的递归算法)
public static int fanco(int n) {
System.out.println("fanco("+n+")");
if (n<=1) {
return 1;
}
return fanco(n-1)+fanco(n-2);
}
由上面的算法运行得知:当n取5时,运行结果如下,它会一直重复执行已经算过的值。分治法的时间复杂度就会成指数增长。动态规划算法完美的解决了这个问题。
动态规划算法: 通过把原问题分解为相对简单的互相不独立的子问题的方式求解复杂问题的方法。它在算出一个子问题的解后,就会把子问题存起来,放到一个数据结构中。在算其他子问题时,首先判断一下,是否已经存在解。用这种放法来减少计算量,避免在重复子问题的数目关于输入的规模呈指数增长问题。所以动态规划算法在查找有很多重叠子问题的情况的最优解时有效。
而且它一般会得到最优值。
斐波那契数列的自底向上动态规划算法。
public static void fanco2(int n) {
int f0,f1,f2;
f0=f1=f2=1;
for (int i = 2; i <= n; i++) {
f2 = f0+f1;
f0 = f1;
f1 = f2;
}
System.out.println(f2);
}
动态规划的一般步骤:
找出最优解的性质并刻画其数据结构,即分析问题来观察问题运用动态规划算法的可行性。
递归的定义最优值,最终得到动态规划方程
以自底向上的方式计算最有值,
根据最优值来得到最优解。
斐波那契数列的自顶向下的动态规划算法:
static int temp[] = new int[1000];
public static int fanco3(int n) {
int t = 0;
if (temp[n] != 0 ) {
return temp[n];
}
if (n==0) t=0;
if (n==1) t=1;
if(n>1) t=fanco3(n-1)+fanco(n-2);
return temp[n]=t;
}
注:动态规划一般会求出一个最优解。