Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >有关动态规划问题DP的详细讲解

有关动态规划问题DP的详细讲解

作者头像
杨鹏伟
发布于 2020-09-11 06:51:58
发布于 2020-09-11 06:51:58
89400
代码可运行
举报
文章被收录于专栏:ypwypw
运行总次数:0
代码可运行

首先我们要注意,我们学习DP主要是学一种解决问题的思想,而不是一种算法。 动态规划的思想 动态规划是求解多阶段决策过程最优化的方法。 通过把多阶段过程转化为一系列的单阶段问题,利用各阶段之间的关系,逐个求解。 找到各阶段之间的关系是难点。 举个栗子~ 矩阵取数问题 从矩阵的左上走到右下,每次只能向右或者向下走,问怎样走才能使得最后走过路径的和最 大。 分析 当然可以用BFS, DFS去暴力搜索出所有的矩阵,但是暴力完全体现不出任何优美。 如果用的思想,应该怎么做?? 首先我们想到的一定是贪心策略,每次只能向右或者向下两种选择,那么 是不是只要每次都选择 右面和下面 的中,其元素最大的那个方向,最后的答案就是最大的呢?

用贪心的方法,答案是9. 但是显然有一个更大的答案 10 ,这个答案是如何得出的? 如果你崇尚暴力的美学,当然也可以把所有的路径搜出来求一个最大值,但是请自行算当N=500时 有多少条路。 我们来用DP的思想来解决这个问题x 设矩阵是 . 假设我们已经知道了最大路径,并且经过(x, y)这个位置,为了从起点到终点得到的和最大,那 么从起点到 (x , y) 经过的数的和也一定要最大。这几乎是显然的。 这是理解这一题的重点。 走到 (x, y) 的上一步,可能是 (x-1, y) 或者(x, y-1). 按照我门上面得出的结论,我们可以这样说: 如果从起点达到(x,y)的最优路径要经过(x – 1,y)或者(x,y – 1)则,从起点到达(x – 1,y)或者(x,y – 1)的 路径一定也必须是最优的。 所以只需要比较 到达(x – 1,y)或者(x,y – 1)的最优路径哪一个更加优。为了方便表示,我们用:f(x,y) 来表示起点到 (x,y)的最优路径长度。 所以,起点到 (x,y)的最优路径可以表示成:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
f(x,y) = max(f(x-1),y),f(x,y-1))+A[x][y];

到了这里肯定会有疑问了,这怎么感觉和上面的贪心策略差不多?? 其实不,这里是理解DP的重点。根据上面的这个递推公式,我门可以准确的推导出从起点到所有点 的最优解。是整体的最优。而贪心策略只是在局部做选择,是局部的最优。

代码实现如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<bits/stdc++.h>
using namespace std;
const int MAXN=500+10;
int a[MAXN][MAXN];
int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
		cin>>a[i][j];
		
	for(int i=1;i<n;i++)
	{
		a[0][1] += a[0][i-1];
		a[i][0] += a[i-1][0];
	}
	for(int i=1;i<n;i++)
	  for(int j=1;j<n;j++)
	   a[i][j] += max(a[i-1][j],a[i][j-1]);
	
	cout<<a[n-1][n-1]<<endl;
	return 0;
} 

再来个栗子,你来练练手~ 最大字段问题 给出一个整数数组a(正负数都有),最多有50000个,如何找出一个连续子数组(可以一个都不 取),使得其中的和最大? 例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13。和为20。

这个问题的暴力解决方案就是一个双层循环, 时间复杂度,50000个数据一定超时。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
for(int i=1;i<=n;i++)
   {
   	  int sum =0;
   	  for(int j=i;i<=n;j++)
   	     {
   	     	sum+=a[j];
   	     	ans = max(anx,sum);
			}
   }

这已经是可以用动态规划思想去考虑的最简单的问题了, 每一步的决策无非就是,是否继续把下一个元素加入当前的子段. 动态规划大显身手。我们开一个数组dp[] , 记录dp[i]表示以a[i]结尾的 全部子段中 最大的那个的 和。 这样我们就可以根据它dp[i] 的正负,去考虑是否把下一个元素加入到当前的子段。 如果dp[i] 是负数,那么我们为什不从a[i+1]新维护一个子段呢? 如果dp[i] 是正数,那么显然可以继续把a[i+1] 加入到当前的子段。 最后我们只需要找出所有最大子段中,最大的那个。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
 #include <cmath>
using namespace std; 
const int MAXN = 50000+10; 
long long a[MAXN]; 
int main()
 {     
     int n; 
    long long ans;   
     cin >> n;     
     for (int i = 0; i < n; i++)         cin >> a[i];  ans = a[0];    
      for (int i = 1; i < n; i++)     { if (a[i-1] > 0)     a[i] += a[i-1];    ans = max(ans, a[i]);}           
       cout << ans << endl; 
    return 0; 
    } 
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/09/13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
顺序表应用8:最大子段和之动态规划法(SDUT 3665)
题解:因为小于0的记为0,所以遍历一遍顺序表就可以,如果当前的sum小于0,那么加上一定不是最优解,所以直接舍去,sum=0,比较sum和当前ans的大小,记录最大值为ans。
Lokinli
2023/03/09
2450
暑假(补)-4
动态规划算法是通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推(或者说分治)的方式去解决。 动态规划算法的基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。
AngelNH
2020/04/16
3620
动态规划——背包问题(详解)
动态规划是我最早接触的算法,一开始非常简单,固定模板题,后来愈发愈发难起来了,条件,状态压缩等等,难点主要是,状态怎么表示,状态转移方程怎么写,这篇文章将会从背包五大问题详解,希望能帮助到大家去类比,思考其他动态规划题目。
全栈程序员站长
2022/09/17
6510
动态规划——背包问题(详解)
poj 1088 记忆化搜索||动态规划
记忆化搜索也也是采用递归深搜的对数据进行搜索,但不同于直接深搜的方式,记忆化搜索是在每次搜索时将得到的结果保存下来,避免了重复计算,这就是所谓的记忆化。记忆化应该是属于动态规划。
xindoo
2021/01/22
3540
51 NOD 1049 最大子段和 动态规划 模板 板子 DP
例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13。和为20。
风骨散人Chiam
2020/10/28
3470
【算法学习】动态规划
动态规划(dynamic programming)是一种基础的算法设计思想。作为一种寻找最优解的通用方法,它是在20世纪50年代由美国数学家Richard Bellman(也就是之前最短路径问题中Bellman ford算法的发明者之一)所发明的。
短短的路走走停停
2019/11/10
7470
【算法学习】动态规划
CF思维联系–CodeForces - 225C. Barcode(二路动态规划)
You’ve got an n × m pixel picture. Each pixel can be white or black. Your task is to change the colors of as few pixels as possible to obtain a barcode picture.
风骨散人Chiam
2020/11/03
4470
【算法】动态规划 ① ( 动态规划简介 | 自底向上的动态规划示例 | 自顶向下的动态规划示例 )
动态规划 , 英文名称 Dynamic Programming , 简称 DP , 不是具体的某种算法 , 是一种算法思想 ;
韩曙亮
2023/03/30
9970
【算法】动态规划 ① ( 动态规划简介 | 自底向上的动态规划示例 | 自顶向下的动态规划示例 )
SDUT 2019 级程序设计基础(B)II 实验6–动态规划
在下面的数字三角形中寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大。路径上的每一步都只能往左下或 右下走。只需要求出这个最大和即可,不必给出具体路径。 三角形的行数n大于1小于等于100,数字为 0 – 99 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5
Here_SDUT
2022/06/29
3340
SDUT 2019 级程序设计基础(B)II 实验6–动态规划
动态规划--Kin
动态规划: 1.最大子序列和 2.LIS最长递增子序列 3.LCS最长公共子序列 4.矩阵连乘 5.数字金字塔 1.最大子序列和 #include<iostream> using namespace std; int maxsub(int a[],int n) { int sum=0,b=0; for(int i=0;i<=n;i++) { if(b>0) b+=a[i]; else b=a[i]; if(b>sum) sum=b; } return s
Kindear
2018/05/09
5500
浅谈我对动态规划的一点理解---大家准备好小板凳,我要开始吹牛皮了~~~
前言 作为一个退役狗跟大家扯这些东西,感觉确实有点。。。但是,针对网上没有一篇文章能够很详细的把动态规划问题说明的很清楚,我决定还是拿出我的全部家当,来跟大家分享我对动态规划的理解,我会尽可能的把所遇到的动态规划的问题都涵盖进去,博主退役多年,可能有些地方会讲的不完善,还望大家多多贡献出自己的宝贵建议,共同进步~~~ 概念 首先我们得知道动态规划是什么东东,百度百科上是这么说的,动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数
Angel_Kitty
2018/04/08
4.6K0
浅谈我对动态规划的一点理解---大家准备好小板凳,我要开始吹牛皮了~~~
【愚公系列】软考中级-软件设计师 056-算法设计与分析(动态规划法和贪心法)
动态规划法(Dynamic Programming)和贪心法(Greedy Algorithm)是两种常用的问题求解方法。它们在某些情况下可以互相替代,但在其他情况下则各有优势。
愚公搬代码
2024/05/06
2070
【算法设计与分析】六、动态规划:(二)上机-1、地牢逃生【理论到程序】
  用一个 n×n 的矩阵表示一座地牢,矩阵中第 i 行第 j 列的方格的值表示位置 (i,j) 的地势高度 h(i,j)。   时间 T=0 的时刻地牢开始下雨,当时间 T=t 时,地牢任意位置的水位都等于t 。任意时刻可以从当前位置游向上下左右四周相邻的任意一个位置,但是游动的前提是:此时水位必须淹没这个位置和其相邻位置,即如果在 T=t 时想从 (i,j) 位置移动到 (i,j+1) 位置,需要满足t≥h(i,j),t≥h(i,j+1) 。假定在方格内部游动不耗时。 时间 T 的取值是正整数。   求:从 (1,1) 位置出发,最少耗时多久可以到达 (n,n) 。
Qomolangma
2024/07/30
1311
【算法设计与分析】六、动态规划:(二)上机-1、地牢逃生【理论到程序】
从暴力递归到动态规划
在之前的文章大家应该也接触到了一些递归的思想,递归的实质就是函数嵌套着函数,在第一个函数运行中间一定会运行多个函数,因此函数退出条件的设置一定要合理,否则会造成堆栈充满,程序异常退出! 那我们今天来看看如何从暴力递归改成动态规划?动态规划的实质又是什么?什么情况下可以让暴力递归改成动态规划?
算法工程师之路
2019/08/05
5420
动态规划理论学习
一个n乘以n的矩阵w[n][n]。存储的都是正整数。棋子起始位置在左上角,终止位置在右下角。每次只能向右或者向下移动一位。把每条路径经过的数字加起来看作路径的长度。最短路径长度是多少?
Michael阿明
2021/02/20
3380
动态规划理论学习
最大子序和,又贪心又DP
力扣题目链接:https://leetcode-cn.com/problems/maximum-subarray
代码随想录
2021/11/16
3350
【算法解题思想】动态规划+深度优先搜索(C/C++)
动态规划(Dynamic Programming,简称 DP)是一种在数学、管理科学、计算机科学和经济学中用于求解决策过程最优化的数学方法。它通过将复杂问题分解成简单的子问题来解决,通过保存子问题的解,避免重复计算,从而提高效率。
摆烂小白敲代码
2024/09/23
1750
【算法解题思想】动态规划+深度优先搜索(C/C++)
快乐AC三道题---第一周
我们要解决的无非是是否把下一个元素加入,是否开始维护一个新的子段。我们开一个数组b[] , 记录b[i],表示以a[i]结尾的全部子段中 最大的那个的 和。 这样我们就可以根据它b[i] 的正负,去考虑是否把下一个元素加入到当前的子段。 如果b[i] 是负数,那么我们为什不从a[i+1]新维护一个子段呢? 如果b[i] 是正数,那么显然可以继续把a[i+1] 加入到当前的子段。最后我们只需要找出所有最大子段中,最大的那个。
杨鹏伟
2020/09/11
3760
动态规划(dynamic programming)
动态规划的基本思想 动态规划的基本思想在于发现和定义问题中的子问题,这里子问题可也以叫做状态;以及一个子问题到下一个子问题之间 是如何转化的 也就是状态转移方程 因此我们遇到一个问题的时候 应该想一想这个问题是否能用某种方式表示成一个小问题,并且小问题具有最优子结构 最优子结构:问题的最优解由相关子问题的最优解组合而成,这些子问题可以独立求解 关于最优子结构 我们来看2个示例 1、求无权有向图中q-t的最短路径 如果q-t间的最短路径经过了点w  那么我们可以证明 q-w  w-t也均是最短路径   所以无
magicsoar
2018/02/06
1.5K0
动态规划(dynamic programming)
『ACM-算法-动态规划』初识DP动态规划算法
一、多阶段决策过程的最优化问题 在现实生活中,有类活 动的过程,由于 它的特殊性,可将过程分成若干个互相阶段。在它的每一阶段都需要作出决策,从而使整个过程达到最好的活动效果。当阶段决策的选取不是任意确定的,它依赖于当前面临的状态,又影响以后的发展,当段决策确定后,就组成一个决策序列,因而也就确定了整个过程的一条活动路线,这个问题看作是个前后关联具有链状结构的 多阶段过程就称为多阶段决策过程,这就称为多阶段决策问题。 多阶段决策过程,是指这样的一类特殊的活动过程,问题可以按时间顺序分解互联系的阶段,在每-个阶段都要作出决策,全部过程的决策是-个决策序列。
风骨散人Chiam
2020/10/28
7050
推荐阅读
相关推荐
顺序表应用8:最大子段和之动态规划法(SDUT 3665)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验