1. 动态规划(DP)算法的基本原理

  • 动态规划过程

    • 每次决策依赖于当前状态,随即又引起状态转移。
    • 一个决策序列就是在变化的状态中产生的,这种多阶段最优化决策解决问题的过程就称为动态规划。
  • DP求解问题所具有的性质

    • [1] 最优子结构性质:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构。

    • [2] 无后效性:与贪心算法一致。不过贪心算法不需要保留上一个问题的最优解,DP需要保留

    • [3] 子问题重叠:区别于分治法。即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。

      最优子结构性质:子问题重叠性质是指在用递归算法自顶向下对问题进行求解时,每次产生的子问题并不总是新问题,有些子问题会被重复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只计算一次,然后将其计算结果保存在一个表格中,当再次需要计算已经计算过的子问题时,只是在表格中简单地查看一下结果,从而获得较高的解题效率。

  • DP的基本步骤
    动态规划的设计都有着一定的模式,一般要经历以下几个步骤

    • [1] 划分阶段:按照问题的时间或空间特征,把问题分为若干个阶段。在划分阶段时,注意划分后的阶段一定要是有序的或者是可排序的,否则问题就无法求解。

    • [2] 每个阶段的状态:各个阶段用不同的状态表示出来。

    • [3] 确定决策,写出状态转移方程(核心):根据相邻两个阶段的状态之间的关系来确定决策方法和状态转移方程。

    • [4] 确定终止条件/边界条件:给出的状态转移方程是一个递推式,需要一个递推的终止条件或边界条件。

  • DP三要素

    • [1] 问题阶段
    • [2] 每个阶段的状态
    • [3] 递推关系:从前一个阶段转化到后一个阶段之间的递推关系

2. 动态规划(DP)基本实例

  • 动态规划的本质

    • 动态规划是用空间换时间的一种方法的抽象。其关键是发现子问题和记录其结果。然后利用这些结果减轻运算量。因为背包的最终最大容量未知,所以,我们得从1到Capacity一个个试。
  • DP的典型应用包括:

    • 斐波纳契数列
    • 0-1背包问题等
    • 最大不降子序列/子序列和
    • 青蛙跳台阶
  • 1. 最大不降子序列和

[1] 题目描述

一个数的序列bi,当b1 < b2 < … < bS的时候,我们称这个序列是上升的。

对于给定的一个序列(a1, a2, …,aN),我们可以得到一些上升的子序列(ai1, ai2, …, aiK),这里1 <= i1 < i2 < … < iK <= N。比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8),(1,3,5,9)等。这些子序列中序列和最大为18,即子序列(1, 3, 5, 9)的和。

你的任务,就是对于给定的序列,求出最大上升子序列和。注意,最长的上升子序列的和不一定是最大的,比如序列(100, 1, 2, 3)的最大上升子序列和为100,而最长上升子序列为(1, 2, 3)。

[2] 输入输出示例

    样例输入:71 7 3 5 9 4 8样例输出:18

[3] 代码(C)

#include <stdio.h>int array[1000];
int dp[1000];
int N;int MaxNoDropSeq()
{int max = 0;int i, j;for (i = 0; i < N; i++){dp[i] = array[i];                           //dp[i]表示,第i个元素之前的非降序和for (j = 0; j < i; j++){if (array[j] < array[i] && dp[i] < dp[j] + array[i])    //第2句保证dp[i]是最大的非降序和{dp[i] = dp[j] + array[i];           //递推关系if (dp[i] > max)max = dp[i];}}}return max;
}int main()
{scanf("%d", &N);int i;for (i = 0; i < N; i++){scanf("%d", &array[i]);}printf("%d\n", MaxNoDropSeq());return 0;
}
  • 2. 跳台阶

[1] 题目描述

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

[2] 输入输出示例

样例输入:
5样例输出:
8

[3] 代码(C)

#include <stdio.h>int main()
{int n;while (scanf("%d", &n)){int array[n + 1];array[1] = 1;       //1级台阶1种跳法array[2] = 2;       //2级台阶2种跳法int i;for (i = 3; i < n + 1; i++){array[i] = array[i - 1] + array[i - 2];     //递推关系}printf("%d\n", array[n]);}return 0;
}
  • 3. 0-1背包问题

[1] 问题描述

一个背包有滴定的承重C,有N件物品,每件物品都有自己的价值,记录在数组V中,也都有自己的重量,记录在数组W中。每件物品只能选择要装入还是不装入背包,要求在不超过背包承重的前提下,选出的物品总价值最大。

在使用动态规划算法求解0-1背包问题时,可选物品为i、i+1、……、n时0-1背包问题的最优值。
价值数组v = {8, 10, 6, 3, 7, 2}
重量数组w = {4, 6, 2, 2, 5, 1}

[2] 问题分析

  • 用dp[i][j]表示前i个物品在总容量不超过j的情况下,放到背包里的最大价值

  • 状态转移方程/递推关系如下

    dp[0][j] = 0

    dp[i][j] = max{dp[i-1][j], dp[i-1][j-v[i]] + w[i]}; {i,j | 0< i <=n, 0<= j <=capacity})

  •  当决定是否放入i时,我们需要考虑两种子问题

    • 【1】 如果放入,那我们考虑在物品数为i-1, 背包容量为j-weight[i]时的价值
    • 【2】 如果不放入,物品数为i-1, 重量为j时的价值
    • 哪一个大,选择哪一个。

[3] 代码(C)

#include <stdio.h>#define N 4             //物品数量
#define Capacity 10     //包容量int max(int a, int b)
{if (a > b)return a;elsereturn b;
}int main()
{int weight[N] = {7,3,4,5};      //物品重量int value[N] = {42,12,40,25};   //物品价值int dp[N + 1][Capacity + 1];int i,j;                        //i:第i件物品; j:容量for (i = 0; i <= N; i++){for (j = 0; j <= Capacity; j++){if (i == 0 || j == 0){dp[i][j] = 0;continue;}if (j >= weight[i])dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);elsedp[i][j] = dp[i - 1][j];}}printf("%d", dp[N][Capacity]);return 0;
}

Acknowledgements:
http://blog.csdn.net/lcj_cjfykx/article/details/41691787
http://blog.csdn.net/ebowtang/article/details/45127659(推荐)
http://blog.csdn.net/uestclr/article/details/50760563(DP其他例题)

2017.09.17

算法与数据结构-DP算法及简单实例相关推荐

  1. 什么是算法?数据结构与算法概念

    算法的概念 算法是计算机处理信息的本质,因为计算机程序本质上是一个算法来告诉计算机确切的步骤来执行一个指定的任务.一般地,当算法在处理信息时,会从输入设备或数据的存储地址读取数据,把结果写入输出设备或 ...

  2. 算法与数据结构(part1)--算法简介及大O表示法

    学习笔记,仅供参考 文章目录 算法与数据结构--基于python 数据结构和算法简介 算法引入 例题A 算法的概念 例题A的优化 算法效率的衡量 时间复杂度与大O记法 例题A的时间复杂度 如何理解大O ...

  3. python数据结构与算法13_python 数据结构与算法 (13)

    python 数据结构与算法 (13) 选择排序 (Selection sort) 是? 种简单直观的排序算法. 它的? 作原理如 下.? 先在未排序序列中找到最?(?)元素, 存放到排序序列的起始位 ...

  4. 循环首次适应算法_数据结构与算法之2——排序问题

    排序真的是数据结构与算法中的重中之重啊,无论是对编程能力的提升,以后工作后的应用,或者是应对面试的时候都是经常需要用到的.基本的几个经典排序一定要做到滚瓜烂熟,能够做到给你一个具体的排序算法题,一定能 ...

  5. 【图解数据结构与算法】数据结构与算法知识点整理 Data Structures and Algorithms

    程序=数据结构+算法 数据结构是可以存储和组织数据的命名位置. 算法是用于解决特定问题的一组步骤. 数据结构是指:一种数据组织.管理和存储的格式,它可以帮助我们实现对数据高效的访问和修改. 数据结构 ...

  6. python数据结构算法_数据结构与算法(Python)

    数据结构与算法(Python) Why? 我们举一个可能不太恰当的例子: 如果将最终写好运行的程序比作战场,我们码农便是指挥作战的将军,而我们所写的代码便是士兵和武器. 那么数据结构和算法是什么?答曰 ...

  7. prim算法_数据结构与算法

    根据MOOC上课程总结,文章目录为: 一.引论 数据结构的基本概念 数据的逻辑结构和存储结构 算法及其时间复杂度 时间复杂度及应用 二.线性表 线性表的概念及顺序存储 单链表的概念及其基本操作 建立单 ...

  8. 尚硅谷01 数据结构与算法_数据结构与算法介绍+稀疏数组

    数据结构与算法的关系 几个实际编程中遇到的问题 要想写出优秀的算法,首先应该能读懂别人写好的算法. 将生活中遇到的实际问题,使用程序来解决 线性结构和非线性结构 线性结构和非线性结构的关系: 数据结构 ...

  9. 【蛮力算法】数据结构与算法

    蛮力算法也称为穷举法或暴力法,它是算法设计中最常见的方法之一.蛮力算法的基本思路是对问题的所有可能状态一一测试,直到找到解或将全部可能状态都测试为止. 蛮力算法的概述 蛮力法是一种简单.直接地解决问题 ...

最新文章

  1. nginx大量TIME_WAIT的解决办法(转载)
  2. Source Insight主题推荐和显示属性设置方法
  3. matlab中plot同时绘制两个函数时向量长度不一致的解决办法
  4. obs多推流地址_抖音obs推流直播怎么操作,抖音直播推流地址如何获取?
  5. MVC POST请求后执行javascript代码
  6. C++描述杭电OJ 2012. 素数判定 ||
  7. 水滴公司再回应“线下违规”:核心是公司的管理问题
  8. (转)法线贴图Nomal mapping 原理
  9. OSPF Sham-Link
  10. mysql 查出数据后插入新建表
  11. 解决桌面单击右键反应慢的问题
  12. 新书出版:《数字滤波器的MATLAB与FPGA实现——Altera/Verilog版(第2版)》已开始印刷出版
  13. 如何制作家庭网络服务器,如何用一个废旧的笔记本打造一个家庭网络服务器?...
  14. JAVA输入任意一个数,判断是否是回文数
  15. 盲打打字php,盲打26键打字口诀是什么
  16. 前端优化 | DOSM Web项目优化分析 ( 附解决方案及代码)
  17. [Android相机]光线传感器识别环境光亮强度
  18. 分区函数Partition By的用法
  19. 数据结构与算法之时间复杂度与空间复杂度
  20. Java解决校验区间值重复问题

热门文章

  1. 游戏图像学习入门到精通-Shader总结篇
  2. 前端本地模糊搜索并高亮
  3. 计算机页面纸张大小19 27,计算机应用基础19.
  4. Vulkan Samples 阅读 -- Hardware Accelerated Ray Tracing(一) Basic Ray Tracing Ray Traced Shadows
  5. 生活短视频网站介绍百科
  6. Chocolatey的安装与使用
  7. chocolatey 安装_如何为Windows安装和使用Chocolatey Package Manager?
  8. c语言里integer用法,integer constant
  9. PLSQL中文显示乱码,真正有效的解决方案(无需修改注册表 )
  10. 网络收发数据中涉及的黏包问题及解决办法