本文总结了《王道机试指南》中动态规划(Dynamic Programming)部分的所有例题以及分析思路、状态转移方程等。有助于完整复习动态规划全部内容。为避免大量代码和题干导致失去主线,本文只写思路,代码可在题目链接内的讨论区找到。

一.基本思想

与分治法类似,其基本思想也是将待求解问题分解成若干子问题,先求解子问题,然后从这些子问题的解中得到原问题的解。
与分治法不同的是,分治法会使得有些子问题被重复计算多次。而动态规划的做法是将已解决子问题的答案保存下来,在需要子问题答案的时候便可直接获得,而不需要重复计算,节约效率。

二.经典题目

1. 递推求解问题

1.1斐波那契数列问题 (n阶楼梯上楼问题)

状态转移方程:dp[n] = dp[n-1] + dp[n-2]

2. 最大连续子序列和

2.1(一维) 最大序列和问题

设置一个数组dp[ ],令dp[i]表示以A[i]作为末尾的连续序列的最大和。
状态转移方程:dp[i] = max{ A[i], dp[i-1] + A[i] }
解释:由于dp[i]是以A[i]作为结尾的连续序列最大和,因此只有两种情况:

  1. 最大和的连续序列只有一个元素,即A[i]本身。也就是dp[i] = A[i]
  2. 该最长子序列有多个元素,那么此时的dp[i] = dp[i-1] + A[i]

所以取最大值即可。

2.2(二维) 最大子矩阵问题

对于二维情况,假设原二维矩阵的最大子矩阵所在的行为 i 到 j 。

  1. 当 i = j 时,则最大子矩阵为第 i 行的最大连续子序列和。(转化为一维)
  2. 当 i != j 时,现在我们已经知道最大子矩阵的行,把从第 i 行到第 j 行的所有元素相加,得到一个只有一行的一维数组,则该一维数组的连续最大和就是最大子矩阵。(同样转化为一维)

3.最长递增子序列

3.1 拦截导弹

同样设置一个数组dp[ ] ,表以A[i]作为末尾的最长递增子序列的长度。
状态转移方程:dp[i] = max{ 1, dp[j] + 1 }。(当 j < i && A[j] < A[i] 时)
解释:由于dp[i]是以A[i]作为末尾的最长递增子序列的长度,因此只有两种情况:

  1. A[i]之前的元素都比A[i]大,即dp[i] = 1。
  2. 存在一些A[ j ]比A[ i ]小,只需找出最大的dp[j] + 1存入dp[i]

则最长递增子序列的长度即为dp中的最大值。

3.2 最大上升子序列和问题

该题目中,用dp表示的便不是长度了,而是以A[i]作为末尾的最大上升子序列和。其原理与求最长递增子序列的原理完全一致。
状态转移方程:dp[i] = max{ A[i], dp[j] + A[i] }。(当 j < i && A[j] < A[i}时)

3.3 合唱队形

这道题有点难,有时间再琢磨。

4.最长公共子序列

4.1 Coincidence(找两个字符串的最长公共子串)

这里要设置一个二维的数组 dp[][]。dp[i][j]表示以S1[i]作为末尾和以S2[j]作为末尾的最长公共子序列的长度。因此通过设置这样一个数组,最长公共子序列的长度便是数组dp[n][m]的值。
仔细说来,S1[i]和S2[j]的关系可分为两种情况:

  1. S1[i] == S2[j],即两个字符相同。此时必定存在一个最长公共子串以这个字符结尾。其他部分等价于S1中前 i - 1 个字符和S2中前 j - 1 个字符的最长公共子串。则这个子串的长度比dp[i-1][j-1]多1。即dp[i][j] = dp[i-1][j-1] + 1
  2. S1[i] != S2[j],那此时最长公共子串为S1中的前 i - 1 个字符和S2中的前 j - 1 个字符中最长公共子串长度的较大者。即dp[i][j] = max{ dp[i-1][j], dp[i][j-1] }

状态转移方程 条件
dp[ i ] [ j ] = dp[ i - 1 ] [ j - 1 ] + 1 S1[ i ] == S2[ j ]
dp[ i ] [ j ] = max{ dp[ i - 1 ] [ j ], dp[ i ] [ j - 1 ] } S1[ i ] != S2[ j ]

但还要注意一下边界情况,当有一个字符串为空时,公共串长度必为0。即dp[i][0] == dp[0][j] == 0
相对于暴力枚举的O(2m+n)复杂度降至了O(mn)。

5.背包问题

5.1 0-1背包 (点菜问题)

该问题描述的是,有n件物品,每件物品的重量为w[i],其价值为v[i],现在有个容量为m的背包,如何选择物品使得装入背包物品的价值最大。
如果暴力枚举所有排列组合,再从中找到最大一组,则时间复杂度为O(2n),下面以O(mn)的时间复杂度解决此问题。

首先设置一个二维数组dp[][],令dp[i][j]表示前 i 个物品装进容量为 j 的背包能获得的最大价值。通过设置这么一个二维数组,数组dp[n][m]值就是0-1背包问题的解。
只考虑第i件物品时,可将情况分为是否放入第i件物品两种:

  1. 对于容量为j的背包,如果不放入第 i 件物品,那么这个问题就转化为将前 i - 1 个物品放入容量为j的背包的问题,即dp[i][j] = dp[i-1][j]
  2. 对于容量为j的背包,如果放入第 i 件物品,那么当前背包的容量就变成了 j - w[i] ,并得到了这个物品的价值 v[i]。那么这个问题就转化成了将当前 i - 1 个物品放入容量为 j - w[i] 的背包的问题,即dp[i][j] = dp[i-1][ j-w[i] ] + v[i]

综上,可得状态转移方程:dp[i][j] = max{ dp[i-1][j], dp[i-1][ j-w[i] ] + v[i] }
转移时要注意j-w[i]的值是否为非负值,若为则代表当前容量无法放入第i件物品,不能进行转移。
再考虑一下边界情况

所以,dp[i][0] = dp[0][j] = 0

6.其他问题

6.1 放苹果

链接:https://www.nowcoder.com/questionTerminal/4f0c1e21010e4d849bde5297148e81d9?f=discussion
来源:牛客网
User: 菜鸟葫芦娃

  • 设dp(m,n) 为m个苹果,n个盘子的放法数目,则先对n作讨论,
  • 当n>m:必定有n-m个盘子永远空着,去掉它们对摆放苹果方法数目不产生影响。即if(n>m) dp(m,n) = dp(m,m)
  • 当n <= m:不同的放法可以分成两类:
    1. 有至少一个盘子空着,即相当于dp(m,n) = dp(m,n-1)
    2. 所有盘子都有苹果,相当于可以从每个盘子中拿掉一个苹果,不影响不同放法的数目,即dp(m,n) = dp(m-n,n)
      而总的放苹果的放法数目等于两者的和,即 dp(m,n) = dp(m,n-1) + dp(m-n,n)
#include <stdio.h>int dp(int m, int n)
{if(n==1) return 1;else if(m==0) return 1;else if(n>m) return dp(m, m);else return dp(m, n-1)+dp(m-n, n);
}int main()
{int m, n;while(scanf("%d %d", &m, &n)!=EOF){printf("%d\n", dp(m, n));}return 0;
}

动态规划经典例题汇总 (附最全题目链接)相关推荐

  1. ヾ(o◕∀◕)ノヾ各种动态规划经典例题(新手向、多类型)

    ヾ(o◕∀◕)ノヾ各种动态规划经典例题(新手向.多类型) 一.前言 ヾ(・ω・`。)我把比较常见的类型的动态规划找了一些经典的例题,适合作为新手的入门例题,用于帮助我们对各种不同的动态规划有所了解,很 ...

  2. 【计算机网络】第三章数据链路层知识点及经典例题汇总

    知识点 1.数据链路层使用的信道主要有以下两种类型:  点对点信道.这种信道使用一对一的点对点通信方式.  广播信道.这种信道使用一对多的广播通信方式,因此过程比较复杂.广播信道上连接的主机很多, ...

  3. 2022天梯赛正式赛(附天梯赛题目链接)

    文章目录 L1-1 今天我要赢 (5 分) L1-2 种钻石 (5 分) L1-3 谁能进图书馆 (10 分) L1-4 拯救外星人 (10 分) L1-5 试试手气 (15 分) L1-6 斯德哥尔 ...

  4. 运筹说 第69期 | 动态规划经典例题讲解

    通过前几期的学习,我们已经学会了动态规划的基本概念和基本原理,并且掌握了动态规划模型的建立和具体的求解方法,本期小编带大家学习动态规划在经济管理中的应用. 除了前面讲到的最优路径.资源分配问题外,动态 ...

  5. 动态规划经典例题:乘积最大连续子数组

    题目: 输入一个整形数组,数组里有正数也有负数.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.求所有子数组的和的最大值.例如数组:arr[]={1, 2, 3, -2, 4, -3 ...

  6. 动态规划经典例题-国王的金矿问题

    金矿问题 问题概述: 有一位国王拥有5座金矿,每座金矿的黄金储量不同, 需要参与挖掘的工人人数也不同.例如有的金矿储量是500kg黄金,需 要5个工人来挖掘:有的金矿储量是200kg黄金,需要3个工人 ...

  7. 动态规划经典例题解析

    一.不同路径问题 题目描述 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为"Start" ). 机器人每次只能向下或者向右移动一步.机器人试图达到网格的右下角 ...

  8. 动态规划经典例题:钢条切割

    一.递归算法 如果在第i个地方切割,就把钢条分为两个长度为i,n-i的钢条,问题转化为求这切割两个钢条的最大价值之和 考虑到不切割时的价值 只要比较不切割时的价值和所有切割情况价值和的最大值即可 递归 ...

  9. 数字三角形(动态规划经典例题)

    资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 (图3.1-1)示出了一个数字三角形. 请编一个程序计算从顶至底的某处的一条路 径,使该路径所经过的数字的总和最大. ●每一步可沿左斜 ...

  10. 【动态规划·经典例题】鸡蛋的硬度

    鸡蛋的硬度 总时间限制: 1000ms 内存限制: 65536kB 描述 最近XX公司举办了一个奇怪(super strange!)的比赛:鸡蛋硬度之王争霸赛.参赛者是来自世 界各地的母鸡,比赛的内容 ...

最新文章

  1. java striptrailingzeros_java – 为什么不BigDecimal.stripTrailingZeros()总是删除所有尾随零?...
  2. 那些年困扰 Linux 的蠕虫、病毒和木马
  3. iptraf 打不开
  4. 如何制作流畅有力的游戏动画+Skullgirls案例分析
  5. ajax清请求过程,JS深入基础之Ajax的请求过程
  6. [expimp]exp导出笔记
  7. 我滴个乖乖,一万三千颗卫星那
  8. 怎么去掉字符串最后一个逗号
  9. 力学 —— 物体固有属性之惯性张量矩阵
  10. 教程:使用Java以编程方式将PLT转换为PDF或图像
  11. 移动WEB开发布局中的-box-sizing:border-box
  12. 树莓派4B连接PCF8591模块
  13. (7,4)汉明码编码译码及计算最小码距——基于MATLAB编程
  14. C# VS2017中Windows窗体更改图标
  15. 网狐大联盟脚本还原数据库
  16. threejs辉光通道01(UnrealBloomPass layers)
  17. 【日本中部电力公司开始着手区块链事业】
  18. 论文笔记-DeepLung: Deep 3D Dual Path Nets for Automated Pulmonary Nodule Detection and Classification
  19. 代数与逻辑:作业一 线性模型
  20. Python+OpenCV教程5:颜色空间转换 追踪视频中特定颜色的物体 消除票据中的红色印章

热门文章

  1. 1124Js基础语法
  2. PX4板载计算机外部控制
  3. HCIE Security PKI 备考笔记(幕布)
  4. LAMP架构调优(六)——开启长链接
  5. EVN双归组网环路问题解决
  6. BUU BRUTE 1
  7. 谁说程序员找不到女朋友,你们是不知道当程序员撩妹,一撩一个准
  8. ZZULIOJ 1917: E
  9. JavaScript 是按值传递还是按引用传递的
  10. 【译】AS3利用CPU缓存