1.以上篇文章数塔为例 https://blog.csdn.net/weixin_43627118/article/details/88701586



上一章用的是递归的做法,这次我们采用递推的做法。

递归:从已知问题的结果出发,用迭代表达式逐步推算出问题的开始的条件,即顺推法的逆过程,称为递归。

递推:递推算法是一种用若干步可重复运算来描述复杂问题的方法。递推是序列计算中的一种常用算法。通常是通过计算机前面的一些项来得出序列中的指定象的值。

递归与递推区别:相对于递归算法,递推算法免除了数据进出栈的过程,也就是说,不需要函数不断的向边界值靠拢,而直接从边界出发,直到求出函数值。

斐波那契数列:已知f(1) = 1 , f(2) = 1 , 且满足关系式f(n) = f(n-1) + f(n-2),则f(50)等于多少?

分析:根据初始条件f(1) = 1 , f(2) = 1 和关系式f(n) = f(n-1) + f(n-2),可知,f(3) = f(2) + f(1) , f(3) = f(2) + f(1) …….

编写代码(递归)

第四层的取值等于左下或者右下与自己的加和,第四层就有max{2+19,2+7} max{18+7,18+10} max{9+10,9+4} max{5+4,5+16}

结果第四层就变成了 21,28,19,21。这样五层变成了四层。以此类推n层变为n-1层到1层。更易求出最大值。

代码实现过程如下

#include<bits/stdc++.h>
using namespace std;
int main
{
int ob[10][10];
int temp;
cin>>N;//数塔层数
for(int i=0;i<N;i++)
{
for(t=0;t<=i;t++)
{
cin>>a[i][j];
}
}
for(int i=N-1;i>=1;i--)
{
for(int t=0;t<=i;t++)
{
temp=max{a[i+1][t],a[i+1][t+1];
a[i][t]=a[i][t]+temp;
}
}
1、线性模型
线性模型的是动态规划中最常用的模型,上文讲到的最长单调子序列就是经典的线性模型,这里的线性指的是状态的排布是性的。
2、区间模型
区间模型的状态表示一般为d[i][j],表示区间[i, j]上的最优解,然后通过状态转移计算出[i+1, j]或者[i, j+1]上的最优解,逐步扩大区间的范围,最终求得[1, len]的最优解。

3、背包模型

背包问题是动态规划中一个最典型的问题之一。由于网上有非常详尽的背包讲解,这里只将常用部分抽出来,具体推导过程详见 《背包九讲》。

a.0/1背包

有N种物品(每种物品1件)和一个容量为V的背包。放入第 i 种物品耗费的空间是Ci,得到 的价值是Wi。求解将哪些物品装入背包可使价值总和最大。

f[i][v]表示前i种物品恰好放入一个容量为v的背包可以获得的最大价值。

决策为第i个物品在前i-1个物品放置完毕后,是选择放还是不放,状态转移方程为:

f[i][v] = max{ f[i-1][v], f[i-1][v - Ci] +Wi }

时间复杂度O(VN),空间复杂度O(VN) (空间复杂度可利用滚动数组进行优化达到O(V),下文会介绍滚动数组优化)。

 b.完全背包
            有N种物品(每种物品无限件)和一个容量为V的背包。放入第 i 种物品耗费的空间是Ci,得到 的价值是Wi。求解将哪些物品装入背包可使价值总和最大。
f[i][v]表示前i种物品恰好放入一个容量为v的背包可以获得的最大价值。
f[i][v] = max{ f[i-1][v - kCi] + kWi | 0 <= k <= v/Ci } (当k的取值为0,1时,这就是01背包的状态转移方程)
时间复杂度O( VNsum{V/Ci} ),空间复杂度在用滚动数组优化后可以达到 O( V )。
进行优化后(此处省略500字),状态转移方程变成:
f[i][v] = max{ f[i-1][v], f[i][v - Ci] +Wi }
时间复杂度降为 O(VN)。
c.多重背包
有N种物品(每种物品Mi件)和一个容量为V的背包。放入第i种物品耗费的空间是Ci,得到 的价值是Wi。求解将哪些物品装入背包可使价值总和最大。
f[i][v]表示前i种物品恰好放入一个容量为v的背包可以获得的最大价值。
f[i][v] = max{ f[i-1][v - kCi] + kWi | 0 <= k <= Mi }
时间复杂度O( Vsum(Mi) ), 空间复杂度仍然可以用滚动数组优化后可以达到 O( V )。
优化:采用二进制拆分物品,将Mi个物品拆分成容量为1、2、4、8、... 2^k、Mi-( 2^(k+1) - 1 ) 个对应价值为Wi、2Wi、4Wi、8Wi、...、2^kWi、( Mi-( 2^(k+1) - 1 )

)Wi的物品,然后采用01背包求解。 这样做的时间复杂度降为O(Vsum(logMi) )。找不到出处了

给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?

输出需要删除的字符个数。

本题可转化为动态规划算法求解最长公共子序列问题,然后用总字符串长度减去最长子序列长度,便得出问题的答案。

先将给定的初始字符串S1反过来排列,设为S2,求S1和S2的最长公共子序列便可。C++代码如下:

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int temp[100][100]; void caculate(string s1){
string s2(s1);
reverse(s2.begin(), s2.end());
int len = s1.length();
memset(temp, 0, sizeof(temp));
for (int i = 0; i<len; ++i)
{
for (int j = 0; j<len; ++j)
{
if (s1[i] == s2[j])
temp[i + 1][j + 1] = temp[i][j] + 1;
else
temp[i + 1][j + 1] = max(temp[i][j + 1], temp[i + 1][j]);
}
}
cout << len - temp[len][len] << endl;
} int main()
{
string s;
getline(cin, s);
caculate(s);
system("pause");
return 0;
}

动态规划分类有很多划分方法,网上有很多是按照状态来分,分为一维、二维、区间、树形等等。我觉得还是按功能即解决的问题的类型以及难易程度来分比较好,下面按照我自己的理解和归纳,把动态规划的分类如下:

一、简单基础dp

这类dp主要是一些状态比较容易表示,转移方程比较好想,问题比较基本常见的。主要包括递推、背包、LIS(最长递增序列),LCS(最长公共子序列),下面针对这几种类型,推荐一下比较好的学习资料和题目。

1、递推:

递推一般形式比较单一,从前往后,分类枚举就行。

简单:

hdu 2084 数塔 简单从上往下递推

hdu 2018 母牛的故事 简单递推计数

hdu 2044 一只小蜜蜂… 简单递推计数(Fibonacci)

hdu 2041 超级楼梯 Fibonacci

hdu 2050 折线分割平面 找递推公式

推荐:

CF 429B B.Working out 四个角递推

zoj 3747 Attack on Titans 带限制条件的计数递推dp

uva 10328 Coin Toss 同上题

hdu 4747 Mex

hdu 4489 The King’s Ups and Downs

hdu 4054 Number String

2、背包

经典的背包九讲:http://love-oriented.com/pack/

推荐博客:http://blog.csdn.net/woshi250hua/article/details/7636866

主要有0-1背包、完全背包、分组背包、多重背包。

简单:

hdu 2955 Robberies 01背包

hdu 1864 最大报销额 01背包

hdu 2602 Bone Collector 01背包

hdu 2844 Coins 多重背包

hdu 2159 FATE 完全背包

推荐:

woj 1537 A Stone-I 转化成背包

woj 1538 B Stone-II 转化成背包

poj 1170 Shopping Offers 状压+背包

zoj 3769 Diablo III 带限制条件的背包

zoj 3638 Fruit Ninja 背包的转化成组合数学

hdu 3092 Least common multiple 转化成完全背包问题

poj 1015 Jury Compromise 扩大区间+输出路径

poj 1112 Team Them UP 图论+背包

3、LIS

最长递增子序列,朴素的是o(n^2)算法,二分下可以写成o(nlgn):维护一个当前最优的递增序列——找到恰好大于它更新

简单:

hdu 1003 Max Sum

hdu 1087 Super Jumping!

推荐:

uva 10635 Prince and Princess LCS转化成LIS

hdu 4352 XHXJ’s LIS 数位dp+LIS思想

srm div2 1000 状态压缩+LIS

poj 1239 Increasing Sequence 两次dp

4、LCS

最长公共子序列,通常o(n^2)的算法

hdu 1503 Advanced Fruits

hdu 1159 Common Subsequence

uva 111 History Grading 要先排个序

poj 1080 Human Gene Functions

二、区间dp

推荐博客:http://blog.csdn.net/woshi250hua/article/details/7969225

区间dp,一般是枚举区间,把区间分成左右两部分,然后求出左右区间再合并。

poj 1141 Brackets Sequence 括号匹配并输出方案

hdu 4745 Two Rabbits 转化成求回文串

zoj 3541 The Last Puzzle 贪心+区间dp

poj 2955 Brackets

hdu 4283 You Are the One 常见写法

hdu 2476 String Printer

zoj 3537 Cake

CF 149D Coloring Brackets

zoj 3469 Food Delivery

三、树形dp

比较好的博客:http://blog.csdn.net/woshi250hua/article/details/7644959

一篇论文:http://doc.baidu.com/view/f3b19d0b79563c1ec5da710e.html

树形dp是建立在树这种数据结构上的dp,一般状态比较好想,通过dfs维护从根到叶子或从叶子到根的状态转移。

hdu 4123 Bob’s Race 二分+树形dp+单调队列

hdu 4514 求树的直径

poj 1655 Balancing Act

hdu 4714 Tree2Cycle 思维

hdu 4616 Game

hdu 4126 Genghis Kehan the Conqueror MST+树形dp 比较经典

hdu 4756 Install Air Conditioning MST+树形dp 同上

hdu 3660 Alice and Bob’s Trip 有点像对抗搜索

CF 337D Book of Evil 树直径的思想 思维

hdu 2196 Computer 搜两遍

四、数位dp

推荐一篇论文:http://wenku.baidu.com/view/d2414ffe04a1b0717fd5dda8.html

数位dp,主要用来解决统计满足某类特殊关系或有某些特点的区间内的数的个数,它是按位来进行计数统计的,可以保存子状态,速度较快。数位dp做多了后,套路基本上都差不多,关键把要保存的状态给抽象出来,保存下来。

hdu 2089 不要62 简单数位dp

hdu 3709 Balanced Number 比较简单

CF 401D Roman and Numbers 状压+数位dp

hdu 4398 X mod f(x) 把模数加进状态里面

hdu 4734 F(x) 简单数位dp

hdu 3693 Math teacher’s homework 思维变换的数位dp

hdu 4352 XHXJ’s LIS 数位dp+LIS思想

CF 55D Beautiful Numbers 比较巧妙的数位dp

hdu 3565 Bi-peak Numbers 比较难想

CF 258B Little Elephant and Elections 数位dp+组合数学+逆元

五、概率(期望) dp

推荐博客:http://www.cnblogs.com/kuangbin/archive/2012/10/02/2710606.html

推荐博客:http://blog.csdn.net/woshi250hua/article/details/7912049

推荐论文:

《走进概率的世界》

《浅析竞赛中一类数学期望问题的解决方法》

《有关概率和期望问题的研究》

一般来说概率正着推,期望逆着推。有环的一般要用到高斯消元解方程。期望可以分解成多个子期望的加权和,权为子期望发生的概率,即

E(aA+bB+…) = aE(A) + bE(B) +…

ural 1776 Anniversiry Firework 比较基础

hdu 4418 Time travel 比较经典BFS+概率dp+高斯消元

hdu 4586 Play the Dice 推公式比较水

hdu 4487 Maximum Random Walk

jobdu 1546 迷宫问题 高斯消元+概率dp+BFS预处理

hdu 3853 LOOPS 简单概率dp

hdu 4405 Aeroplane chess 简单概率dp,比较直接

hdu 4089 Activation 比较经典

poj 2096 Collecting Bugs 题目比较难读懂

zoj 3640 Help me Escape 从后往前,比较简单

hdu 4034 Maze 经典好题,借助树的概率dp

hdu 4336 Card Collector 状态压缩+概率dp

hdu 4326 Game 这个题状态有点难抽象

六、状态压缩dp

这类问题有TSP、插头dp等。

推荐论文:http://wenku.baidu.com/view/ce445e4f767f5acfa1c7cd51.html

推荐博客:http://blog.csdn.net/sf____/article/details/15026397

推荐博客:http://www.notonlysuccess.com/index.php/plug_dp/

hdu 1693 Eat the Trees 插头dp

hdu 4568 Hunter 最短路+TSP

hdu 4539 插头dp

hdu 4529 状压dp

poj 1185 炮兵阵地

poj 2411 Mandriann’s Dream 轮廓线dp

hdu 3811 Permutation

poj 1038

poj 2441

hdu 2167

hdu 4026

hdu 4281

七、数据结构优化的dp

有时尽管状态找好了,转移方程的想好了,但时间复杂度比较大,需要用数据结构进行优化。常见的优化有二进制优化、单调队列优化、斜率优化、四边形不等式优化等。

1、二进制优化

主要是优化背包问题,背包九讲里面有介绍,比较简单,这里只附上几道题目。

hdu 1059 Diving

hdu 1171 Big Event in Hdu

poj 1048 Follow My Magic

2、单调队列优化

推荐论文:http://wenku.baidu.com/view/4d23b4d128ea81c758f578ae.html

推荐博客:http://www.cnblogs.com/neverforget/archive/2011/10/13/ll.html

hdu 3401 Trade

poj 3245 Sequece Partitioning 二分+单调队列优化

3、斜率优化

推荐论文:用单调性优化动态规划

推荐博客:http://www.cnblogs.com/ronaflx/archive/2011/02/05/1949278.html

hdu 3507 Print Article

poj 1260 Pearls

hdu 2829 Lawrence

hdu 2993 Max Average Problem

4、四边形不等式优化

推荐博客:http://www.cnblogs.com/ronaflx/archive/2011/03/30/1999764.html

推荐博客:http://www.cnblogs.com/zxndgv/archive/2011/08/02/2125242.html

hdu 2952 Counting Sheep

poj 1160 Post Office

hdu 3480 Division

hdu 3516 Tree Construction

hdu 2829 Lawrence

摘自博客地址 https://blog.csdn.net/qq_41785863/article/details/81489269

矩阵连乘问题,纸牌问题,石头合并问题(都是一类问题,一起分析)

给定n个矩阵{A1,A2……An},其中A【i】与A【i+1】是可乘的,如何确定计算的次序,使得乘法的总次数最少

首先我们要明白,计算的次序不同,那么乘法的总次数也不同

类似的问题:给你n张牌,每张排都有一个数字,相邻的两张牌的权值可以相乘,相乘的两张牌可以合并为

一张牌,新牌的权值是原来的两张牌的乘积

这个问题还有石头合并问题都是同一类的问题,属于区间dp问题

石头合并问题:给你一堆石头,排成一行,相邻的两个石头可以合并,合并成的石头的权值为原来两个石头

的权值之和

先来分析矩阵连乘问题:

给你一个一维数组

30,35,15,5,10,20,25

只要相邻的矩阵才可以相乘

思考一下,dp的思想是如何体现的

第一步我们是要把问题分解成很多互相有联系的子问题(重复子问题是用dp的基础)

简单的思考一下,每次矩阵相乘,最简单的就是两个可以相乘的矩阵相乘(A1,A2,A3),那最大的乘法次数就是A1A2A3

但是如果是多个呢,我们是不是可以简化成下面这样

A【i】,A【i+1】………………….A【k】………………A【j-1】,A【j】

讲他们分成两个抽象矩阵

第一个:A【i】….A【k】

第二个:A【k+1】……A【j】

把大问题抽象成两个抽象矩阵相乘,那么更加最简单的那种抽象一下就知道求所有矩阵乘法的最大次数,就

是求第一个抽象矩阵自己内部要乘的次数和第二个抽象矩阵内部自己要求的乘法次数然后加上这这两个抽象

矩阵合并为一个大的抽象矩阵要乘的次数

那么大问题是这样的,大问题里面是不是有很多这样的小问题,而且这些小问题还是重复的,比如A【k】

的选择不同,那么乘的次序结果也不一样,A【k】的选择可以导致很多问题都有重复的部分,如果多次计

算的话,无疑是很不明智的,这样的话跟分治就是没有什么区别了,这样的问题就叫做重复子问题

A【k】的选择不同的话,会导致子问题有很多重复的部分,前面我们说了的,同时A【k】的选择不同的话

会导致两个抽象矩阵相乘的结果也不一样,所以我们就要在所有的A【k】选择中找一个最小的

所以我们现在在这个问题里面找到了dp思想的具体体现:大量的重复子问题

具体做法:

dp【i】【j】:代表矩阵i,矩阵i+1………….矩阵j的最少乘法次数

总结上述:

dp【i】【j】=min(dp【i】【k】+dp【k+1】【j】

i<=k<=j-1 https://blog.csdn.net/qq_39382769/article/details/80788294

通过例题进一步学习DP的更多相关文章

  1. 过实现鹰眼图这个功能来进一步学习MapControl控件

    我们通过实现鹰眼图这个功能来进一步学习MapControl控件.在实现鹰眼图之前,我们需 要接口有更深入的了解. 变主动为被动-出接口(OutBound interface) COM编程类似客户端和服 ...

  2. 对Linux命令进一步学习vim(二)

    今天,进一步学习Linux相关的命令,可能会有重复的地方,但学习本来就是不断重复的过程.故作小记! 1.安装了:vim  ,,,一款Linux爱好者经常用到的ide sudo apt-get inst ...

  3. legend2---开发日志12(vue如何进一步学习)

    legend2---开发日志12(vue如何进一步学习) 一.总结 一句话总结:还是得找教程(比如视频),自己摸索太浪费时间,也容易踩坑和抓不住重点 还是得找教程(比如视频),自己摸索太浪费时间,也容 ...

  4. PHP Loser 说说做前端需要如何进一步学习

    PHP Loser 说说做前端需要如何进一步学习 做前端的,需要如何进一步学习?书籍这个事情贵精不在多,我这里推荐两本即可: <javascript教程 高级程序设计> <CSS权威 ...

  5. abp学习(四)——根据入门教程(aspnetMVC Web API进一步学习)

    Introduction With AspNet MVC Web API EntityFramework and AngularJS 地址:https://aspnetboilerplate.com/ ...

  6. dp方法论——由矩阵相乘问题学习dp解题思路

    前篇戳:dp入门——由分杆问题认识动态规划 导语 刷过一些算法题,就会十分珍惜“方法论”这种东西.Leetcode上只有题目.讨论和答案,没有方法论.往往答案看起来十分切中要害,但是从看题目到得到思路 ...

  7. 省选算法学习-dp优化-四边形不等式

    嗯......四边形不等式的确长得像个四边形[雾] 我们在dp中,经常见到这样一类状态以及转移方程: 设$dp\left[i\right]\left[j\right]$表示闭区间$\left[i,j\ ...

  8. 2020/1/29 PHP代码审计之进一步学习XSS【持续更新】

    0x00 上午学习了XSS漏洞,中午吃饭想了想,还是思考的太浅层了,这种老生常谈的东西对于现在的我意义不大.现在我需要的是思考.于是就有了这个随笔.在本文中,我会持续更新一些XSS的深入思考,payl ...

  9. 梳理一下最近准备蓝桥杯时学习DP问题的想法

    学习时间不长,记录的只是学习过程的思路和想法,不能保证正确,代码可以在acwing上AC. 01背包问题: 1.首先是简单的01背包问题 2.先确定状态,f[i][j]表示有第i件物品,时间为j的最大 ...

随机推荐

  1. MTK Android 源码目录分析

    Android 源码目录分析 Android 4.0 |-- abi (application binary interface:应用二进制接口)|-- art (average retrieval ...

  2. .NET MVC中登录过滤器拦截的两种方法

    今天给大家介绍两种ASP中过滤器拦截的两种方法. 一种是EF 的HtppModule,另一种则是灵活很多针对MVC的特性类 Attribute 具体什么是特性类可以参考着篇文章:https://www ...

  3. 关于node中两个模块相互引用却不会死循环的问题

    关于node中两个模块相互引用却不会死循环的问题 node中是通过require来导入加载模块的,require有两个作用: 1.加载文件模块并执行里面的代码 2.拿到被加载文件模块导出的接口对象 现 ...

  4. 讲讲HashMap的理解,以及HashMap在1.7和1.8版本的变化(2020/4/16)

    HashMap的适用场景,作用,优缺点

  5. AJ学IOS(08)UI之热门_喜马拉雅UI实现-UIScrollView的使用

    AJ分享,必须精品 先看效果 storyBoard用到的控件 代码实现 */ // // NYViewController.m // 05 - 喜马拉雅 // // Created by apple ...

  6. 【做中学】第一个 Go 语言程序:漫画下载器

    原文地址: 第一个 Go 语言程序:漫画下载器: https://schaepher.github.io/2020/04/11/golang-first-comic-downloader 之前学了点 ...

  7. 用Python绘制全球疫情变化地图

    目前全球疫情仍然比较严重,为了能清晰地看到疫情爆发以来至现在全球疫情的变化趋势,我绘制了一张疫情变化地图,完整代码共 230 行,需要的朋友在公众号回复关键字 疫情地图 即可. 废话不多说,先上图 下 ...

  8. react性能优化最佳实践

    1.PureComponent 的使用场景 PureComponent 和 Component 的区别是,PureComponent 自带 shouldComponentUpdate 生命周期函数,会 ...

  9. C - Highways poj1751最小生成树

    The island nation of Flatopia is perfectly flat. Unfortunately, Flatopia has a very poor system of p ...

  10. 详解 final 和 static

    在我们上一篇博文中提到了 fianl 这个关键字,对于这个关键字,本人在初学时也耗费了极大地心血,甚至和师兄进行了激烈的讨论,并且,在我们讨论.尝试 以及 翻阅各种资料,最终得出了合适.易懂的解释. ...