【专章】dp入门

时间:2021-02-06 18:21:17

知识点

动态规划(简称dp),可以说是各种程序设计中遇到的第一个坎吧,这篇博文是我对dp的一点点理解,希望可以帮助更多人dp入门。

 

先看看这段话

动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法。20世纪50年代初美国数学家R.E.Bellman等人在研究多阶段决策过程(multistep decision process)的优化问题时,提出了著名的最优化原理(principle of optimality),把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解,创立了解决这类过程优化问题的新方法——动态规划。1957年出版了他的名著《Dynamic Programming》,这是该领域的第一本著作。

这是百度百科上对于动态规划介绍,其实dp并没有这么复杂,可以把dp看作是记忆化搜索的递推形式。

再来看一下下面这段文字(来自《挑战程序设计竞赛(第二版)》):

【专章】dp入门

【专章】dp入门

【专章】dp入门

就像上面所说的,对于一道题目,如果选择搜索可能会出现大量重复的状态,如函数f

 int f(int a,int b)
{
return f(a+,b+)+f(a-,b-);
}

这种函数在计算过程中有大量的资源被浪费,如 f(1,1) 和 f(3,3) 在返回值时都会计算一次 f(2,2),这种无谓的计算致使了动态规划的诞生。

动态规划算法通常基于一个递推公式及一个或多个初始状态。当前子问题的解将由上一次子问题的解推出。使用动态规划来解题只需要多项式时间复杂度,因此它比回溯法、暴力法等要快许多。

现在让我们通过一个例子来了解一下DP的基本原理。

首先,我们要找到某个状态的最优解,然后在它的帮助下,找到下一个状态的最优解。

(上面这段话看不懂也就别看了)

其实简单的来说,dp就是用数组来递推下一个状态。

像上面的f函数,写成dp就是 f[a][b] 。递推式也与函数基本相同:f[a][b]=f[a-1][b-1]+f[a+1][b+1]。用这个式子,双重循环即可。


 

例题

如下是几个经典问题,对于初学者来说有一点点难度,不懂可以多看几篇关于dp入门的文章。此处附上我的代码。题目可以百度。

最好要理解,并能独立实现代码

1、01背包

2、最长上升子序列(简称LIS,两种做法,一种是O(n2),另一种是O(nlogn))

3、最长公共子序列(简称LCS)


看完了上面的,可以做做题练练手了。

下面是一些题目的练习,题目都在www.luogu.org上,可以配合里面的题解与我的代码来理解。


习题

下述题目都为基础的dp包括经典问题与其各种变形,乃dp入门必备之题。

注意: 1、从最下面往上刷


最后提供一些练习题与详解:传送门

刷完了进入下一章:dp基础

洛谷P1280 尼克的任务

逆序dp,详见注释

洛谷P1091 合唱队形

从头开始,从尾开始各跑一次LIS

洛谷P1115 最大子段和 dp

洛谷P1508 Likecloud-吃、吃、吃

洛谷P1510 精卫填海

洛谷P1855 榨取kkksc03

洛谷P1216 [USACO1.5]数字三角形 Number Triangles

洛谷P1910 L国的战斗之间谍

洛谷P2925 [USACO08DEC]干草出售Hay For Sale

洛谷P2347 砝码称重

洛谷P2722 总分 Score Inflation

开始dp入门的征程吧!

------------------------------------------------------------------------------------------

后继章:dp基础