初探动态规划(DP)
学习qzz的命名,来写一篇关于动态规划(dp)的入门博客。
动态规划应该算是一个入门oier的坑,动态规划的抽象即神奇之处,让很多萌新 萌比。
写这篇博客的目标,就是想要用一些容易理解的方式,讲解入门动态规划的真正意义。
奶萌兔的温馨提示:建议先理解dfs哦~(本文以一种较为新奇的方式解释DP)
动态规划
那什么是动态规划?
来问问神奇的奶萌兔吧(强行盗梗)!
(奶萌兔来给你讲解啦~虽然还在睡觉=w=)
- 动态规划(英语:Dynamic programming,简称DP)是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。
- 动态规划常常适用于有重叠子问题[]和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。
- 动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再根据子问题的解以得出原问题的解。
- 通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量:一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。
- 这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。----来自wiki百科
说这么多,DP能干什么?
奶萌兔的回答:解决一些问题...解决一些,dfs效率无法通过的问题。
不如先讲一道例题:
例1
爬楼梯:现在有n层楼梯,奶萌兔位于第0层 现在奶萌兔每一次可以往上爬1层或者2层,问奶萌兔爬到第n层有多少种方案?
这是一道经典的入门题,对于这道题,我们由简入深。
如何dfs?
这样考虑 dfs(int dep) 表示奶萌兔在第dep层。
那有两个走法,一个是dfs(dep+1) 一个是dfs(dep+2)。
而dfs的边界呢? 则是 n 。 即 if (dep>n) return;
初始值? dfs(0) 从第0层开始。
对于答案的统计? 那就是每当dep为n时,说明到达了对ans统计加1。 即 if (dep==n) ans++ 且return;
说了怎么多dfs?对dp有个什么用啊!!!
这时候,奶萌兔来引入一个东西——状态。
状态是什么?用浅显易懂的解释就是,dfs需要保存的东西(不一定...),如dfs(int dep) dep(奶萌兔当前的层数)就是一个状态。
而dp则是利用状态之间的相互关联,答案得以更新。
那下面,来讲 如何dp?
这样考虑 DP[dep] 表示奶萌兔从第0层走到第dep层时的方案数
依旧有两个走法,一个是DP[dep+1] 一个是DP[dep+2]。
是不是和dfs很相似? 接下来是重点。
初始值 dp[0]=1 到第0层有一种方案,就是一开始就在0层。
DP[dep+1] DP[dep+2]会等于什么?
DP[dep+1]+=DP[dep] DP[dep+2]+=DP[dep]
因为走到第dep层的方案是DP[dep],那么在走一层的时候,就只能走到dep+1的地方,那么dep上的全部方案,在通过走一步这样唯一的一个方法,可以到达dep+1,所以走到dep+1包含了dep上的方案,dep+2同理。
上面的两个式子就是状态转移方程了。
简单的转化一下, dp[dep+1]+=dp[dep] dp[dep+2]+=dep[dep] 则dp[dep]=dp[dep-1]+dp[dep-2] (当然不转化也是可以的,但对于部分题目,一些转化之后可能可以因此优化效率)
例2
从一个一维的题目,试试跳到二维。
骑士遍历:第一问可以直接往字典序最小去dfs,所以直接关注第二问吧
第二问:给一个n*m的棋盘,给定起点x1,y1 终点 x2,y2 在只能走日且只能向右走的情况下,问方案数。
这是例1的拓展,从一维的向上走,变为二维的向右走。
首先对于这样的棋盘,我们是不习惯的,因为与我们的数组顺序不同,让人烦心。
那怎么办捏?问问神奇的奶萌兔!
奶萌兔幽幽的说了一句:对~称~旋~转~
哈!这是原来的题
哈!这还是原来的题
于是旋转一下之后,棋盘还是原来的棋盘,只是方向改变了。
题目就变成了只走日字且向下走的情况。
老规矩呢,如何dfs?
用用新名词,状态,dfs的状态是什么? dfs(int x,int y) 表示当前奶萌兔骑士在(x,y)的位置。
那就是有四个走法
dfs(x+1,y+2) dfs(x+2,y+1) dfs(x+1,y-2) dfs(x+2,y-1)
边界 0 ,n 0 ,m 即 x>0且x<=n y>0且y<=m
初始:dfs(x1,y1)
答案的统计:每当 x==x2&&y==y2 时说明到终点了,那ans++
dp类比就好啦,状态就是数组的下标。
DP[x][y] 表示奶萌兔骑士从(x1,y1)出发到(x,y) 的位置时的方案。
一样四个走法
DP[x+1][y+2] DP[x+2][y+1] DP[x+1][y-2] DP[x+2][y-1]
边界是一样的哦~
初始:DP[x1][y1]=1 (在起点的时候就是一个方案)
答案:DP[x2][y2]
那转移方程,和例1一样哦,只是拓展为二维,走法变多一些。
DP[x+1][y+2]+=DP[x][y] DP[x+2][y+1]+=DP[x][y] DP[x+1][y-2]+=DP[x][y] DP[x+2][y-1]+=DP[x][y]
简单转化一下: dp[x][y]=dp[x-1][y-2]+dp[x-2][y-1]+dp[x-1][y+2]+dp[x-2][y+1];
好了问题来了:怎么转化的? 不妨这样撕烤,固定住(x,y) 找找哪些点能到(x,y) 那些点的方案数加起来就是了(或者,对前面的方程变化,x+d改为x-d,y+d改为y-d (d为常数))。
- #define ll long long
- #include<cstdio>
- #include<iostream>
- using namespace std;
- ll f[][];
- int ansx[],ansy[];
- int n,m,x1,x2,y1,y2;
- const ll HR=1e18;
- void dfs(int dep,int nowx,int nowy){
- ansx[dep]=nowx;
- ansy[dep]=nowy;
- if (nowx==n&&nowy==m) {
- for (int i=;i<dep;i++)
- printf("(%d,%d)-",ansx[i],ansy[i]);
- printf("(%d,%d)",ansx[dep],ansy[dep]);
- exit();
- }
- //dfs的顺序注意按字典序最小。
- if (nowx+<=n&&nowy->) dfs(dep+,nowx+,nowy-);
- if (nowx+<=n&&nowy+<=m) dfs(dep+,nowx+,nowy+);
- if (nowx+<=n&&nowy->) dfs(dep+,nowx+,nowy-);
- if (nowx+<=n&&nowy+<=m) dfs(dep+,nowx+,nowy+);
- }
- int main(){
- scanf("%d%d%d%d%d%d",&n,&m,&x1,&y1,&x2,&y2);
- if (x1==) {
- dfs(,,); //第一问
- printf("NO");
- return ;
- }
- //第二问
- f[x1][y1]=;
- for (int i=x1+;i<=x2;i++){ //从x1+1开始,因为x1这一行是不可能更新的。
- for (int j=;j<=m;j++){
- if (j->) f[i][j]+=f[i-][j-]; //边界
- f[i][j]%=HR;
- f[i][j]+=f[i-][j+];
- //为什么这个不判?原因是f[i-1][j+2]的值一定是0,因为无法更新到边界外的数,而初始值都是0,注意把数组开大即可,下面同理
- f[i][j]%=HR;
- f[i][j]+=f[i-][j-];
- f[i][j]%=HR;
- f[i][j]+=f[i-][j+];
- f[i][j]%=HR;
- }
- }
- printf("%lld",f[x2][y2]);
- return ;
- }
例2
以上就是入门的方案数dp。
后期可能更新其他dp呀~
初探动态规划(DP)的更多相关文章
- 动态规划dp
一.概念:动态规划dp:是一种分阶段求解决策问题的数学思想. 总结起来就一句话:大事化小,小事化了 二.例子 1.走台阶问题 F(10):10级台阶的走法数量 所以:F(10)=F(9)+F(8) F ...
- 算法-动态规划DP小记
算法-动态规划DP小记 动态规划算法是一种比较灵活的算法,针对具体的问题要具体分析,其宗旨就是要找出要解决问题的状态,然后逆向转化为求解子问题,最终回到已知的初始态,然后再顺序累计各个子问题的解从而得 ...
- 初探 插头DP
因为这题,气得我火冒三丈! 这数据是不是有问题啊!我用cin代替scanf后居然就AC了(本来一直卡在Test 18)!导致我调(对)试(排)了一个小时!! UPD:后来细细想想,会不会是因为scan ...
- 【转】动态规划DP
[数据结构与算法] DP 动态规划 介绍 原创 2017年02月13日 00:42:51 最近在看算法导论. DP全称是dynamic programming,这里programming不是编程,是一 ...
- 动态规划DP的优化
写一写要讲什么免得忘记了.DP的优化. 大概围绕着"是什么","有什么用","怎么用"三个方面讲. 主要是<算法竞赛入门经典>里 ...
- hdu 1421:搬寝室(动态规划 DP + 排序)
搬寝室 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...
- hdu 2059:龟兔赛跑(动态规划 DP)
龟兔赛跑 Time Limit : 1000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) Total Submissi ...
- Luogu 2627 修建草坪 (动态规划Dp + 单调队列优化)
题意: 已知一个序列 { a [ i ] } ,求取出从中若干不大于 KK 的区间,求这些区间和的最大值. 细节: 没有细节???感觉没有??? 分析: 听说有两种方法!!! 好吧实际上是等价的只是看 ...
- 动态规划DP入门
百度百科↓ 动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法.20世纪50年代初美国数学家R.E.Bellman ...
随机推荐
- kubernetes 创建tomcat 容器
方案一: 使用k8s dashboard 创建rc 1. 界面操作 提示:暂时 忽略 查看: 2.测试 由于是外部服务 直接用 节点的ip访问: 同样也是 第二个端口可以访问.感觉 跟之前的提 ...
- WEB安全番外第六篇--关于通过记录渗透工具的Payload来总结和学习测试用例
背景: 在WEB安全的学习过程中,了解过了原理之后,就是学习各种Payload,这里面蕴藏着丰富的知识含量,是在基本上覆盖了漏洞原理之后的进一步深入学习的必经之路.无理是Burpsuite还是Sqlm ...
- [黑金原创教程] FPGA那些事儿《设计篇 III》- 图像处理前夕·再续
简介 一本为入门图像处理的入门书,另外还教你徒手搭建平台(片上系统),内容请看目录. 注意 为了达到最好的实验的结果,请准备以下硬件. AX301开发板, OV7670摄像模块, VGA接口显示器, ...
- awk中的冒泡排序
算法中经典的排序方式,今也用awk来实现下,代码如下: BEGIN { count=} {arrary[count]=$ count++ } END{ ;i>-;i--) { ;j<i;j ...
- 【Android】Scrollview 相关问题汇总
去除Scrollview 滑动边界渐变颜色 去掉滚动条,并将在滑动时,边界不会变成灰白 <horizontalscrollview android:overScrollMode="ne ...
- Eclipse初体验
Eclipse有很多个版本: 这里我们下载Eclipse for javaEE版,既可以写javaSE代码又可以写web代码,省去了很多插件配置的时间.官网下载地址:http://www.eclips ...
- [NGINX] - 配置文件优化 - NGINX.CONF
Nginx 本文主要针对公司的Nginx负载均衡配置进行解释,配置文件在最下方.因为公司没有使用PHP,所以NGINX里面并没有太多facgi模块相关优化 NGINX.CONF user 语 ...
- 解决IE7下scroll的bug
IE7下scroll滚动问题 没法撑开 ie7下没办法撑开div; 即是设置了overflow-y:scroll; 解决版本:给设置scroll的容器加上position:relative
- 系统性能优化- Session丢失
最近在做项目的过程中,客户经常反馈在操作的时候进场会突然跳转到登录页面. 先描述下系统情况: 操作系统:WindowsServer 2008 .NET版本:.NET 4.0/ASP.NET 4.0/A ...
- 原来css可以直接覆盖内联style
今天阅读博文新手如何在gdb中存活时,发现行距太小,阅读起来不舒服. 查看了一下html代码,发现是博文内容中的内联style(line-height: normal)覆盖了博客模板的css引起的. ...