算法分析与设计第二版(李春葆)第八章动态规划

一、动态规划的原理

动态规划是一种解决多阶段决策问题的优化方法,把多阶段问题转换为一个个单阶段问题,利用各个阶段之间的关系求解

二、动态规划法的性质

最优解原理:问题的最优解包含的子问题也是最优的。

无后效性:该问题状态一旦确定,就不受这个状态以后决策的影响。

有重叠子问题:子问题之间不独立。子问题的解在下一段决策时可能会被多次使用到,就像计算Fib(5)时可能用到Fib(3),储存到数组中。这也正是动态规划相较于其他算法的优势。

三、动态规划法的一般步骤:

  1. 分析最优解的性质和结构特性

  2. 递归地定义最优值

  3. 自底向上(递推)的方式求解最优值

  4. 根据最优值的信息构造最优解

四、动态规划的例子(8.8或8.5为填空题最后一题)

8.2求解整数拆分问题:

备忘录方法是动态规划方法的变形,在我的理解中就是递归和DP数组的结合,因为采用了递归所以是自顶向下,而动态规划只利用了DP数组,从i,j=0开始计算,所以是自底向上

动态规划自底向上:

#include <stdio.h>
#define MAXN 500
int dp[MAXN][MAXN];			//动态规划数组
void Split(int n,int k)		//求解算法
{
	for (int i=1;i<=n;i++)
		for(int j=1;j<=k;j++)
		{
			if (i==1 || j==1)
				dp[i][j]=1;
			else if (i<j)
				dp[i][j]=dp[i][i];
			else if (i==j)
				dp[i][j]=dp[i][j-1]+1;
			else
				dp[i][j]=dp[i][j-1]+dp[i-j][j];
		}
}
void main()
{
	int n=5,k=5;
	Split(n,k);
	printf("(%d,%d)=%d\n",n,k,dp[n][k]);	//输出:7
}

备忘录法自顶向下 

//求解整数拆分问题的算法
#include <stdio.h>
#include <string.h>
#define MAXN 500
int dp[MAXN][MAXN];
int dpf(int n,int k)
{
	if (dp[n][k]!=0) return dp[n][k];
	if (n==1 || k==1)
	{
		dp[n][k]=1;
		return dp[n][k];
	}
	else if (n<k)
	{
		dp[n][k]=dpf(n,n);
		return dp[n][k];
	}
	else if (n==k)
	{
		dp[n][k]=dpf(n,k-1)+1;
		return dp[n][k];
	}
	else
	{
		dp[n][k]=dpf(n,k-1)+dpf(n-k,k);
		return dp[n][k];
	}
}
void main()
{
	int n=5,k=5;
	memset(dp,0,sizeof(dp));				//初始化为0
	printf("dpf(%d,%d)=%d\n",n,k,dpf(n,k));	//输出:7
}

8.5求解最长公共子序列问题(重点,填表,根据表格找出最长公共子序列)

 

8.8求解0/1背包问题(填表+追溯最优解)

状态转移方程

例题

追溯最优解很简单,首先从右下角找起,右下角和上一行同列比较,如果相同则代表没有选i行的物品,最优解向量x[i]=0,再对i-1行同样操作。如果不一样,就代表选了,则x[i]=1,用剩余背包容量r-w[i],并找到r-w[i]列,对该列进行相同的操作。

 复习题:算法分析与设计(李春葆)第八章1~8

先这样,等复习到后面再来复习一遍填表和追溯最优解。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值