动态规划入门到放弃(一)

动态规划的基本概念

阶段和阶段变量

将问题的全过程恰当地分为若干个相互联系的阶段。阶段的划分一般根据时间和控件的自然特征去划分,阶段的划分要吧问题转化为多阶段决策问题。

状态和状态变量

通常一个阶段包含若干个状态
状态可有变量表述

决策 决策变量和决策允许集合

在对问题的处理中做出的每种选择性的行动就是决策,即从该阶段的每一个阶段出发,通过一次选择性的行动转移至下一阶段的相应阶段。
在实际问题中,决策变量的取值往往限制于某一个范围内

策略和最优策略

所有阶段一次排列构成问题的全过程。
全过程中各阶段决策变量所组成的有序总体称为策略
在实际问题中,从决策允许集合中找出最优效果的策略称为最优策略

状态转移方程

前一阶段的终点就是后一阶段的起点,对前一阶段的状态做出某种决策,产生后一种阶段的状态,这种关系描述了从i阶段到i+1阶段状态的演变规律,称为状态转移方程.

例子1

从n个数中取出k个数,使得他们的和最大。
f[i][j]表示现在考虑到第i个数,已经选出了j个数
为了详解动态规划,不选用常用做法
阶段:i表示1~i个数
状态:j 选了几个数
决策:选不选?
策略 :值最大
状态转移方程:
在这里插入图片描述
在这里插入图片描述

例子2

从n个数中找出最长的上升子序列
f[i][j]表示目前考虑到第i个数,子序列中最后一个数是j的最长上升子序列长度。
阶段:i
状态:j
决策:对第i个数取还是不取
策略:最大化取序列
状态转移方程:
考虑a[1~n]
f[i][a[[i]]考虑a[i]选取,那就要在a[i]的前面选取一个最大的数,即可以用1+max{f[i-1][j]|j<=a[i]}
要是不考虑a[i]选取,f[i][j]=f[i-1][j];

动态规划的性质

什么样的“多阶段决策问题”才可以用动态规划的方法来求解呢?
必须满足两个条件:
最优化原理
无后效性原则

最优化原理

在这里插入图片描述
例如f[n][k]取最大,取决于f[n-1][k],那么就要a[n]+f{n-0][k-1]最大。

无后效性原则


就是f[n-1][k]中之后这个状态我取不取都无影响,也就是之前已经是最优解,不能用之前的影响未来

不符合上述两个原则的,不能用动态规划来解

动态规划的设计方法

正推:从初始状态开始,通过对中间阶段的决策的选择,达到结束状态。我们也称递推。
在这里插入图片描述
反推:从结束状态开始,通过对中间阶段的决策的选择,达到开始状态,我们可以把这种方法看出记忆化搜索。
dp(n)=dp(n-1)*n;
把每一步dp(n)存在一个数组里面,这样就能保证下次访问时从数组中取出来,不用在此递归。
我们只要在开始的时候,设立一个边界值就可。

动态规划设计方法的一般模式

在这里插入图片描述

动态规划与记忆化搜索

记忆化搜索

实现一个函数,用"搜索" 的方法实现DP的更新。
通常用于转移顺序不方便人为确定的DP

例题 数塔

在这里插入图片描述
每一层就有一个阶段,有若干个状态,某一个状态可以转移到下面两个点,,一直到最后一层
设f[i][j]表示第i行第j列的最大值
正常DP:
在这里插入图片描述
走到[i][j]的最大值
在这里插入图片描述

这样算有一个致命缺点,每次计算都会进行一次递归,这就是记忆化的来源,那对于计算过的dp(i,j),我们用f[i][j]来存
f初始化为-1

int dp(int i,intj)
{
	if(i==0)
		return 0;
	if(f[i][j]>=0)
		return f[i][j];
	f[i][j]=a[i][j]+max(dp(i-1,j),dp(i-1,j-1));
	return f[i][j];
}

例题二

在这里插入图片描述

int dp(int i, int j)//从i j出发最远能滑行的距离
{
	if (f[i][j] > 1)
		return f[i][j];//返回已经存储的值
	for (int k = 0; k < 4; k++)//枚举四个方向可以转移
	{
		int x = i + dx[k], y = j + dy[k];//每个方向上的唯一
		if (x >= 1 && x <= r && y >= 1 && y <= c)//在地图里面
		{
			if (a[i][j] > a[x][y])//满足高度在下降
				f[i][j] = max(f[i][j], dp(x, y) + 1);//从x,y能滑的点在加一
		}
		return f[i][j];
	}
}

这样就通过记忆化搜索更新,使用记忆化搜索比较直观一些,因为使用了记忆化,那我们的时间复杂度也有了保证,因为每次都进行了存储。


for (int i = 1; i <= r; i++)
{
	for (int j = 1; j <= c; j++)
		f[i][j] = 1;
}
int ans = 0;
for (int i = 1; i <= r; i++)
	for (int j = 1; j <= c; j++)
		ans = max(dp(i, j), ans);

printf("%d\n", ans);

博主今天晚上刚刚接触的动态规划,脑子有点懵,如有错误还请指教!!!!!!!!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值