动态规划:把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解;
适用条件
任何思想方法都有一定的局限性,超出
了特定条件,它就失去了作用。同样,动态规划也并不是万能的。适用动态规划的问题必须满足最优化原理和无后效性。
1.最优化原理(最优子结构性质) 最优化原理可这样阐述:一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。简而言之,一个最优化策略的子策略总是最优的。一个问题满足最优化原理又称其具有最优子结构性质。
2.无后效性将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的决策,而只能通过当前的这个状态。换句话说,每个状态都是过去历史的一个完整总结。这就是无后向性,又称为无后效性。
3.子问题的重叠性 动态规划将原来具有指数级时间复杂度的搜索算法改进成了具有多项式时间复杂度的算法。其中的关键在于解决冗余,这是动态规划算法的根本目的。动态规划实质上是一种以空间换时间的技术,它在实现的过程中,不得不存储产生过程中的各种状态,所以它的空间复杂度要大于其它的算法。
算法例子:
1.钢条切割
Serling 公司购买长钢条,将其切割为短钢条,切割工序假设没有成本支出,公司管理层希望确定最佳的切割方案。
假设Serling公司出售一段长度为i英寸的钢条的价格为pi。钢条的长度为整英寸,下表给出了价格表。
长度i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
价格pi | 1 | 5 | 8 | 9 | 10 | 17 | 17 | 20 | 24 | 30 |
最优子结构:
public static int cut(int[] p ,int n){
int[] r = new int[n];
for(int j=1;j <= n;j++){
int q = -1;
for(int i=0;i<= j;i++){
q = Math.max(q,p[j]+ r[j-i]);
}
r[j] = q;
}
return r[n];
}
2.最长公共子序列算法:LCS
最优子结构
public static int lcsLength(String x ,String y){
int m = x.length();
int n = y.length();
int[][] c = new int[m+1][n+1];
int i,j;
for(i=0; i< m+1;i++)
c[i][0] = 0;
for(i=0;i< n+1;i++)
c[0][i] = 0;
for(i=1;i<=m;i++){
for(j=1;j<=n;j++){
if(x.charAt(i) == y.charAt(j))
c[i][j] = c[i-1][j-1]+1;
else if(c[i-1][j] > c[i][j-1])
c[i][j] = c[i-1][j];
else
c[i][j] = c[i][j-1];
}
}
return c[m][n];
}