动态规划自我总结

动态规划总体思想

动态规划的基本思想:

利用空间换取时间,一种自底向上的求解策略,记录中间过程,来避免大量的重复运算。

动态需要满足三个条件:

  1. 最优子结构性质
  2. 无后效性
  3. 重叠子问题性
    这三条性质针对的方向不同:
    解释1:即问题的最优策略序列的子序列最优。即最优子问题最终可以推出原问题的最优解。
    解释2:子问题之间相互独立,各个子问题解决后不会对后面子问题的解决产生影响。
    解释3:子问题实现的方法与策略应该是一样的,性质不变。

动态规划实现步骤

1. 验证最优子结构性质;
2. 建立递归式;
3. 自底向上求取最优;
4. 根据找到的最优值回溯,找到最优序列。

说明:如果题目仅仅要求求取最优值,则前三布实现后就可以停止了。

动态规划具体实例

Fibonacci数:

利用数组,存储算出的数字,这样就避免了大量的初始值的重复运算
在这里插入图片描述
如图所示,
如果利用表,把f(18)记录下来 , 则绿色框中的运算可以省去,直接查表可得;
同理,如果记录下f(17)的数字,则蓝色框中的计算可以省去,直接查表可得,依此类推。

多段图最短路径:

描述:
在这里插入图片描述
递归关系:
在这里插入图片描述

0/1背包问题:

递归关系:

f ( i ,y ) 为以背包容量y,放置物品 i,… ,n得到的优化效益值:

f ( 1 , y ) = max ( f ( 2 , c ) , f ( 2 , c - w[1] ) + v[1] );
f ( i , y ) = max ( f ( i+1 , y ) , f ( i+1 , y - w[i] ) + v[i] ) 当y > w[i]时;
f ( i , y ) = f ( i+1 , y ) 当 y < w[i]时;

边界条件:
f ( n , y ) = v[n] ; w[n] <= y;
f ( n , y ) = 0 ; w[n] > y;

学会填表

void dynamic( ){
	for ( int i = 0 ; i < w; i++ )
		dp[0][i] = 0;
	for ( int i = 0 ; i < n; i++ )
		dp[i][0] = 0;
		//填表的边界条件
	for ( int i = 1 ; i <= n ; i++ ){
		for ( int j = 1 ; j <= w ; j++ ) {
		if ( j  < w[i] ) 
			dp[i][j] = dp[i+1][j];
		else{
			dp[i][j] = max ( dp[i+1][j] , dp[i+1][j-w[i]] + v[i] );
			}
		}//注意递归关系的应用	
}

回溯:

void find ( int i , int j ) {
	if ( i >= 0 ) {
		if ( dp[i][j] ==dp[i-1][j] ){
			item[i] = 0;
			find ( i-1 , j );
			}
		else if ( dp[i][j] != dp[i-1][j] && 
				  dp[i][j] == dp [i-1][j-w[i]]+ v[i] &&
				  j-w[i] >= 0 ) {
				  item[i] = 1;
				  find ( i-1 , j-w[i] ) ;
			}//注意回溯时递归关系的逆运用
		}
}

元组法的重要应用:

在这里插入图片描述
在这里插入图片描述

完全背包,多重背包问题:

递归式
c ( i , y ) = c ( i+1 , y ) 当 y < w[i]时;
c ( i , y ) = max ( c ( i+1 , y ) , c( i+1, y-k*w[i] ) + v[i]k ) 当 y >= kw[i]时;
完全背包问题是01背包的一个扩展,求解该问题,可以在01背包第二个条件分支内,加一个循环,判断加入题目要求数量件以后,是否超重,其他的差不太多。

int result = 0; 
if (i ==  0 || c  == 0){ // 初始条件
 	result = 0; 
 	} 
 else if(w[i] > c)
 { // 装不下该珠宝
 result = ks2(i-1, c); 
} 
 else { // 可以装下,取k个物品,取其中使得价值最大的
 	for (int k = 0; k ≤ mi && k ⋅ wi ≤ c; k++){ 
 		int tmp2 = ks2(i-1, c - w[i] ⋅ k) + v[i] ⋅ k; 
 		if (tmp2 > result){ 
 			result = tmp2; 
 		} 
 	} 
 } 
 results[i][c] = result; 
 return result;

矩阵乘法链:

递归条件:

c ( i , j ) = 0 ( if i = j )
c ( i , j ) = ri * ri+1 * ri+2 ( if j = i+1 )
c ( i , j ) = min ( c ( i , k ) + c ( k+1 , j ) + ri*r(k+1) *r(j+1) ) ( if j > i+1 )

伪代码:

void MatrixChain(int r[], int q, int **c, int **kay)
{
	for (int i=1; i<q; i++){
	c[i][i] = 0; // 边界 i = j 的情况
	c[i][i+1] = r[i]*r[i+1]*r[i+2];// 次边界 j = i+1 的情况
	kay[i][i+1] = i;
}
c[q][q] = 0;
for (int s = 2; s< q; s++){
	for (int i = 1; i <= q – s; i++){
	//k = i 时的最小项
	c[i][i+s]=c[i][i]+c[i+1][i+s]+r[i]*r[i+1]*r[i+s+1];
	kay[i][i+s] = i;
	for (int k=i+1; k<i+s; k++){
		int t=c[i][k] + c[k+1][i+s]+r[i]*r[k+1]*r[i+s+1];
		if (t < c[i][i+s]){
			//更小的最小项	
			c[i][i+s] = t;
			kay[i][i+s] = k; 
		}
	 } 
	}
  }
 }

ALL-PAIR 最短路径问题:

在这里插入图片描述
递归关系
Cij(k) = min ( Cij( k-1 ) , Cik(k-1)+ Ckj(k-1));
具体实现主要是维护一个矩阵:
在这里插入图片描述
查找序列,主要是维护一个前驱矩阵:
在这里插入图片描述

TSP问题:

不多说,直接上图,虽然我觉得TSP用动态规划有点牵强。
在这里插入图片描述
在这里插入图片描述

总结:

动态规划十分重要,注意记录中间过程的思想,以及学会填表,记住递归式,就可以轻松解决很多问题。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值