动态规划

每当一个dp问题做错了,都可以参照一下检查自己的认知。

动态规划题目性质:重叠子问题+最优子结构

递推写法是自底向上,从边界开始不断向上解决问题,直到解决了目标问题

递归写法是自顶向下,从目标问题开始,将它分解成子问题的组合,知道分解至边界为止。

贪心(类似于自顶向下): 通过策略直接选择一个子问题去求解,没被选择的子问题不去考虑

dp(从边界开始得到目标问题的解):对暂时没有被继承的子问题,后期可能会再次考虑它们。

状态的无后效性:当前状态记录了历史信息,一旦当前状态确定,就不会再改变,且未来的决策只能在已有的一个或若干个状态的基础上进行,历史信息只能通过已有的状态去影响未来的决策。(举例:每次计算dp[i],只会用到dp[i-1],不会用到dp[i-1]包含的历史信息) eg.在gymxxxB里面的dp,状态不满足无后效性这一要求

先前看多过一个说法:问什么设什么

在DAG上的dp问题中,如果用dp[i]表示以i为起点的最长路,那么需要按照逆拓扑序排序,递归满足这个,如果要输出路径,应该记录后继结点,这个很容易保证字典序最小。

边界是出度为0的点

int dp(int i)
{
	if(dp[i]>0) return dp[i];
	int &ans=dp[i];
	for(int j=0;j<n;++j)
		if(G[i][j])
		{
			int tmp=G[i][j]+dp(j);
			if(tmp>ans)
			{
				ans=tmp;
				choice[i]=j;
			}
		}
	return ans;
}

void print(int i)
{
	printf("%d",i);
	while(choice[i]!=-1)
	{
		i=choice[i];
		printf("->%d",i);
	}
}

如果固定终点T,边界是dp[T]=0; 出度为0的点为无法到达的点-INF。再开个vis数组标明是否计算过;

 

背包问题:

01背包:如果是二维数组存放,v枚顺序和逆序无所谓,使用一维必须逆序

 

在大多数情况下,都可以把动态规划可解问题看作一个DAG,图中节点是状态,边是状态转移的方向,求解问题的顺序是按照拓扑序或者逆拓扑序。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值