动态规划概述
动态规划是将多阶段决策问题进行公式化的一种技术,它是运筹学的一个分支,用于求解多阶段决策过程的最优化问题。
总体思想
动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,经分解得到的子问题往往不是互相独立的,有些子问题被重复计算多次,如果能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,就可以避免大量重复计算,从而得到多项式时间算法。拒绝重复!
基本要素
-
最优子结构
一个问题的最优解包含着其子问题的最优解,这种性质称为最优子结构性质,分析问题的最优子结构性质:首先假设由问题的最优解导出的子问题的解不是最优的,然后再设法说明在这个假设下可构造出比原问题最优解更好的解,从而导致矛盾,利用问题的最优子结构性质,以自底向上的方式递归地从子问题的最优解逐步构造出整个问题的最优解,最优子结构是一个问题能用动态规划算法求解的前提。 -
重叠子问题
递归算法求解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次,这种性质称为子问题的重叠性质。动态规划算法,对每一个子问题只解一次,而后将其解保存在一个表格中,当再次需要解此子问题时,只是简单地用常数时间查看一下结果,通常不同的子问题个数随问题的大小呈多项式增长,用动态规划算法只需要多项式时间,从而获得较高的解题效率。
**这里与其相似的解法叫做备忘录法:
备忘录法是一种记忆化搜索,备忘录方法的控制结构与直接递归方法的控制结构相同,区别在于备忘录方法为每个解过的子问题建立了备忘录以备需要时查看,避免相同子问题的重复求解亦叫查表法。
动态规划之数字三角形问题
思路: 设p[i][j]表示(i, j)的达到最后一层的最大路径和,那么p[i][j]的最优解包含了子问题p[i+1][j]或p[i+1][j+1]的最优解,其中a数组是用来保存每个点上的值的。
状态转移方程(递归方程):
举个栗子:
具体代码实现
import java.util.Scanner;
public class Main {
public int max(int a,int b){
if(a>b) return a;
else return b;
}
public void solve(int a[][],int p[][],int n){
for(int i=0;i<n;i++){
p[n-1][i]=a[n-1][i];
}
for(int i=n-2;i>=0;i--){
for(int j=0;j<=i;j++){
p[i][j]=a[i][j]+max(p[i+1][j],p[i+1][j+1]);
}
}
}
public static void main(String args[]){
Scanner scan=new Scanner(System.in);
while(scan.hasNext()){
int n=scan.nextInt();
int a[][]=new int[n][n];
int p[][]=new int[n][n];
for(int i=0;i<n;i++){
for(int j=0;j<=i;j++){
a[i][j]=scan.nextInt();
}
}
Main d=new Main();
d.solve(a, p, n);
System.out.println(p[0][0]);
}
scan.close();
}
}
小结
使用动态规划算法求解数字三角形问题,可以去除重复路径,时间复杂度为O(n^2) ,空间复杂度为 O(n^2).