首页 > 其他分享 >动态规划——从入门到入土

动态规划——从入门到入土

时间:2023-02-12 20:44:25浏览次数:50  
标签:状态 入门 int 最大值 入土 设计 动态 dp

什么是动态规划?

动态规划,英文名为Dynamic Programming,又称DP(当然小写的dp也行),是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。由于动态规划并不是某种具体的算法,而是一种解决特定问题的方法,因此它会出现在各式各样的数据结构中,与之相关的题目种类也更为繁杂。在 OI 中,计数等非最优化问题的递推解法也常被不规范地称作 DP。

dp的重要性?

在作者打过的镇赛,区赛乃至GDOI,CSP中,dp一直是常考的东西。所以学会dp尤为关键。

举个例子,2017-2022年的镇赛,区赛中dp常作为压轴题出现,甚至NHOI 2022中T5,T6都是dp。

动态规划入门

先来看这样一道题:P1216 [USACO1.5][IOI1994]数字三角形 Number Triangles(学校OJ 1351)

尽管这道题是IOI的,但不妨碍我们切掉

想必有人会考虑贪心,即如果左边大一点就往左边走,右边大一点就忘右边走。看到给出的样例,就知道这个方法不可行了。如果还想继续从第二大值,第三大值等等情况考虑,你就发现深陷其中无法自拔了。

接下来我们通过这道例题详细分析以下如何做一道动态规划的题目:

Step 1:设计状态

对于动态规划,设计一个状态是做题的第一步。这里初学者可能不知道状态是什么,但是请先耐心看下去。

比如这道题,我们定义一个二维数组 \(f_{i,j}\) 表示的是从起点 \((1,1)\) 走到当前点 \((i,j)\) 的最大值。这里 \(f_{i,j}\) 就表示一个状态。

一般而言,设计的状态通常都是由所需要的答案决定,如本题需要的就是从起点 \((1,1)\) 走到终点的最大值。

请注意,设计出一个好的状态非常重要!请注意,设计出一个好的状态非常重要!请注意,设计出一个好的状态非常重要!(重要的话说三遍!!!

Step 2:设计转移方程

显然,设计好一个状态后,我们需要考虑这个状态的答案应该如何计算得到的,即设计转移方程

例如本题,我们可以画一个表格分析:

\((i-1,j-1)\) \((i-1,j)\)
\((i,j-1)\) \((i,j)\)

显然,我们发现,有两种可以走到当前点 \((i,j)\) 的方法:

  1. \((i-1,j-1)\xrightarrow{}(i,j)\),这时答案应该为从 \((1,1)\) 走到 \((i-1,j-1)\) 的最大值再加上当前取 \((i,j)\) 格子的价 \(a_{i,j}\),即\(f_{i-1,j-1}+a_{i,j}\)。
  2. \((i-1,j)\xrightarrow{}(i,j)\),这时答案应该为从 \((1,1)\) 走到 \((i-1,j)\) 的最大值再加上当前取 \((i,j)\) 格子的价 \(a_{i,j}\),即\(f_{i-1,j-1}+a_{i,j}\)。

我们要的是最大值,所以对两种情况取一个最大值即可得到当前状态 \(f_{i,j}\) 的答案。即

\[f_{i,j}=\max(f_{i-1,j-1}+a_{i,j},f_{i-1,j}+a_{i,j}) \]

或者可以写成

\[f_{i,j}=\max(f_{i-1,j-1},f_{i-1,j})+a_{i,j} \]

f[i][j]=max(f[i-1][j-1]+a[i][j],f[i-1][j]+a[i][j]);//写法1
f[i][j]=max(f[i-1][j-1],f[i-1][j])+a[i][j];//写法2

Step 3:确定答案

根据题意,我们知道终点可以是最后一行的任意一个格子,即 \(f_{n,i}\) ,这里的 \(i\) 可以是 \(1\sim n\) 的其中一个,即 \(1\le i\le n\)。不妨枚举这个 \(i\),然后对于所有的 \(f_{n,i}\) 求一个最大值即可。

Code Time:

#include<bits/stdc++.h>
using namespace std;
const int N=1005;
int n;
int a[N][N],f[N][N];
int ans;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=i;j++)
			scanf("%d",&a[i][j]);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=i;j++)
			f[i][j]=max(f[i-1][j-1],f[i-1][j])+a[i][j];
	for(int i=1;i<=n;i++)ans=max(ans,f[n][i]);
	printf("%d",ans);
	return 0;
}

总结

这是我总结的dp的三步走方案,熟记这三个步骤你可以完成大部分的简单dp,从而入门dp。

对于这道题的一个题外话

对于 Step 2:设计转移方程 不一定有唯一的答案,如本题可以用倒推的方案去设计,即从这两个方案入手。具体代码就不展示了,留给读者自行思考吧。

\[(i,j)\xleftarrow{}(i+1,j) \]

\[(i,j)\xleftarrow{}(i+1,j+1) \]

下面给几道例题巩固一下:

标签:状态,入门,int,最大值,入土,设计,动态,dp
From: https://www.cnblogs.com/DaYanZaiHappy/p/17114678.html

相关文章

  • 第一章-scala入门
    第1章Scala入门1.1概述1.1.1为什么学习Scala1)Spark—新一代内存级大数据计算框架,是大数据的重要内容。2)Spark就是使用Scala编写的。因此为了更好的学习Spar......
  • 大爽Python入门教程 2-7 *拓展实践,对比与思考
    大爽Python入门公开课教案点击查看教程总目录本文偏难。推荐等第一二三四章上完后,回过来拓展阅读。基础情景思考假设有这样一张成绩表最左边的一列是名字,起名麻......
  • 大爽Python入门教程 2-6 拓展练习
    大爽Python入门公开课教案点击查看教程总目录方位输出第一章有一个思考题,方位变换:小明同学站在平原上,面朝北方,向左转51次之后(每次只转90度),小明面朝哪里?小明转过......
  • PLC入门笔记9
    梯形图电路之电机控制电机直接启动控制电路      电机正反停控制电路  我的图。。        但愿最后说的不要发生吧例如下错了程......
  • OpenEBS动态创建存储
    简介​​OpenEBS​​是一种开源云原生存储解决方案,托管于​​CNCF​​基金会,目前该项目处于沙箱阶段,​​OpenEBS​​是一组存储引擎,允许您为有状态工作负载(​​StatefulSet......
  • Filter过滤器 快速入门
    Filter过滤器举例:饮水机空调 web中的过滤器:当访问服务器的资源时过滤器可以将请求拦截下来完成一些特殊功能过滤器的作用一般用来完成通过的操作如......
  • CesiumJS PrimitiveAPI 高级着色入门 - 从参数化几何与 Fabric 材质到着色器 - 上篇
    目录0.基础0.1.坐标系基础0.2.合并批次1.参数化几何1.1.几何类清单1.2.举例1.3.纯手搓几何1.4.*子线程异步生成几何2.使用材质2.1.外观API2.2.材质API2.3.Fa......
  • Java入门
    Java&JDK简介Java是sun公司在1995年开发的一门计算机高级编程语言Java早期被称为Oak(橡树),商标被注册,后期改为Java(印度一个盛产咖啡的小岛)Java的爸爸:JamesGosling2009年......
  • PLC入门笔记8
    梯形图基础电路起保停电路 多点起保停电路    互锁控制电路    周期闪烁电路      这应该是等价的!! 定时器的接力电路  ......
  • 当小球遇上盒子——组合计数入门
    当小球遇上盒子一套排列组合题:盒子是否相同,球是否相同,能否有空盒子共8个状态PS:代码上\(f,g\)的两个维度是反着写的PS:\({n\choosem}=\frac{n!}{m!(n-m)!}=C_n^m\)盒不......