前请提示:https://www.cnblogs.com/caiyishuai/p/9047991.html   配合这篇文章食用风味更佳哦!

首先十分感谢henry_y提供的50道dp练习,链接在这—>https://www.cnblogs.com/henry-1202/p/9211398.html

虽然现在只做了30多道题,剩下的题目还没写,想着以后留着复习来用,但是我对dp的理解比以前高出了不少,现在我来说说对dp的想法吧。

目录

一.动态规划的本质,以及它的核心难点:如何判断这题用dp来解

关于我做到的关于dp以外的技巧

一.动态规划的本质,以及它的核心难点:如何判断这题用dp来解

其实说白了,用到动态规划的题目肯定要满足无后效性,最优子问题这两个关键,但是有些十分有趣的现象,就是如果我们看到一道题,别人没有跟你讲这道题正解是用dp做的,你横看竖看这题也不像dp,那怎么办呢?(这里给出一个实例,有兴趣的可以看一下这题 回文字串 https://www.luogu.org/problem/P1435),那么这些什么无后效性的概念对于我们现在来讲就是废话,因为我们是真的看不出来这题竟然能用dp做,那么现在我给出我自己对这些题目的浅薄理解。

首先,要用dp解题应要立于题目本身,题目要求有求“最大”,“最小”,“最优”等字眼时,应该要想到这题可能要用到dp;

其次,没有头绪时不用慌,观察题目给的样例数据,看看数据都是关于什么,比如背包问题,数据常见的给出有关于价值、容量、重量等等关键元素,这时候就要想一下如果我用dp来写这题,该怎么写。

举个例子,我用dp的思路,常见的就是用F[ i ][ j ]这种二维形式来推出答案,这时候我们应该要想, i 能表示什么,j能表示什么,假设出一种可能后,看看能不能、可不可以写出动态转移方程。

这里我给出一个实例,刚刚那题回文字串,看了题目一脸疑惑,第一反应肯定是暴力,硬搜出答案出来,但是肯定会炸裂,那该怎么办?

我们来看它求什么,“最少插入字符数”,你看!最少这个字眼出现了,直接把解题思路集中在贪心、搜索(这个万不得已的时候才用,因为剪枝技术不行的话,99%超时)、dp等找最优解的算法上(欢迎大家来补充,因为我的知识有限,只了解这些。。。),那么如何来区分是贪心还是dp来解题呢?这里我不再进行解答,开头给出的文章有详细的解析。

我们把目光回到那道题目上面,怎么做?我们可以看到样例有大写字母,小写字母,数字等不同的字符,注意到了吗?不同的字符—>种类(找到第一个元素)每个字符占着不同的位置 —>位置(找到第二个元素) 字串的长度—>长度(找到第三个元素)就这么多吧。

我们再来看看题目的要求,回文字串,题目样例是Ab3bd,如果我们插入它的倒序db3bA,即Ab3bddb3bA,不就是个回文字串吗?而且这么做的话,最后字串个数肯定是偶数,因为倒过来加上去字符个数就是2n,那么我们还可以舍弃最后一个字母来加上去,意思是样例是Ab3bd,回文字串把它变成Ab3bdb3bA,把d给删掉一个,不也是个回文字串吗?那么我们就很容易得出结论  加上去的字符数最多是  原字串长度减去1,(这里先看到下面 1 长度 这个元素)但是有个问题,我原本就有对称趋势的字符,如果这么加,不就浪费了吗?就像样例中的b3b,本已回文,何必再加(看到下面 2 种类 这个元素),那么如何判断这些可以构成回文的部分呢?根据刚刚的思路,倒过来后这些本来已经回文的子串还是回文的,那么不就有点像LCS了吗?我们只需找出那些倒过来还是可以弄成回文的子串(就算是断断续续的也无妨),不就问题迎刃而解?(看到下面 3 位置 这个元素)

现在我们要选一下哪些有用,而且要把它们应用在动态转移方程上面

1 长度 找到了长度这个元素!那怎么可以把它用到方程里面,对于样例而言,长度为5,那么我们只能从5开始,从中间位置开始向两边枚举,但是没有dp的思想在里面啊,否决!

2 种类 回文串的种类个数是串的长度/2(单数串长度还要+1)   我们是否能这么设置?f[ i ][ j ]表示前i 个字符一共有J种种类而需要插入的个数构成的回文串这样子的呢?我们也易看到得出的结果跟我下一个需要判断的阶段好像没啥关系,因为我还是要扫一遍,这不就是搜索了吗?否决!

3 位置 刚刚分析过了,如果我倒过来的串的位置与原串的同一位置的字符一样,那不就看出来这是有对称趋势的字符?配合LCS的思路,最后求出来的就是所以有对称趋势的字符的个数的值,那么我们要求出最少插入的值不就是原串长度-求出的值不就是答案呢吗?为什么呢?把那些没有对称趋势的字符复制在它的“对面”,这个字符就与自己的复制体就对称了,不就从而弄出来答案就是剩下的没有对称趋势的字符的个数吗?而剩下的没有对称趋势的字符不就等于原串长度-求出的值。

以上就是我对其中一题的理解,即是当我没有任何思路时,会去想的方法。 绝不是我事先知道这题是dp才往那方向死命想的

总结一下以上的想法,我就是把题目里面能想到的元素都写出来,再根据题目要求一个个去尝试,因此我在做这些题目时,开了一维的数组,发现好像不行,那就开二维,二维不行就上三维,直到把我能想到的且最终有用的元素都用上。

关于我做到的关于dp以外的技巧

1.尼克的任务(https://www.luogu.org/problemnew/solution/P1280)

这道题可谓是惊天水题,太水了,水的我都溺死了,一开始我一股脑的用常规dp思路,所谓常规就是i=1~n;j=1~n;F[ i , j ]=.......,结果发现连样例都过不了,一看题解,正解要倒序......。这题我怨气这么多一是因为这是50道dp里面的第3道,说是入门级别的难度我实属是不敢相信,二是因为我在找题解,看正解为什么应该要用倒序时,发现了一些dalao,他们写题解都是怎样的呢?“唔~普及组水题”“这题显然是....”等等,我很想说一句,但凡你们认真一点,照顾照顾一下我这些菜鸡,写题解时多一点解释,少一点显然,我也不至于对dp一直有种畏惧的心理。额,这些都是题外话,回到题目,这题可能是我见过的第一道要用倒序dp来做的题目(除去背包问题),算是长见识了。最后说一句,这题一点都不水!

2.LIS的n log n 做法(50道题目里面比较多用到)

这个做法我一开始是一脸懵逼的,最后理解了才发现,其实这种做法不仅仅能适用于这里,这更算是一种思想,一种最优化的思想,我觉得有点难解释,我把这种做法比喻成排队吧,如果有人比现在这个队列里面最高的人还要高,就把他放在最前面,如果不够最高那个人高,就在队列里面找到所有比他高的人里面最矮的那一个,然后把它替换,这样有利于把后面的人给加进来,为什么呢?如果一个人170,他想要加入队伍,现在这个队伍里面最高的人是175,第二高的人是168,这时候我把175的换走,人数不变,此时最高的是170,便于以后想要加进来的171、172、173、174的人排到最前面,队伍人数增多,而不是让他们走人。

3.对dp出来一遍的数组再进行dp一遍(https://www.luogu.org/problem/P1108)

长见识了,我现在都云里雾里的对这题

4.dp与离散化的结合(https://www.luogu.org/problem/UVA10635、https://www.luogu.org/problem/P1439)

这几题以后一定要重新做一遍,对于一些有两个排序标准的题目很有帮助,而且我初步了解到了离散化数据的魅力,其实这个理解起来也不难,就是对于随便一串东西,把它做成一个映射,变成有排列顺序的数字1 2 3 4 等等,做完题输出的时候再反向映射一遍,巧妙吧,我特别想问谁发明的,真的牛啤。

4.Dilworth定理的意思:最少的下降序列个数就等于整个序列最长上升子序列的长度  (有些东西记住就好,不要太在意,要不然头顶会凉)

5.断链成环(https://www.luogu.org/problem/P1063)

这个我要重点提一下,因为我对环的知识还没有很深,所以做题常常碰壁,这题也不例外,那这题怎么说呢?这题让我懂得了一个道理,我设出来的东西可以不用,我可以只是为了我的代码简洁,循环起来不用写那么多限制条件,最后输出的时候输出我要求的东西就行。回归正题吧,环的处理有两种,可以选择(i+1)%n的方式,但也可以将n个元素复制一遍,变成2*n个元素,简化代码,我刚刚说的道理就是从2*n个元素这种方法得出来的。总而言之,我之后要做多一点关于环的题目吧。

6.与二分的结合(https://www.luogu.org/problem/P3957)

虽然核心dp代码里面没有用到二分优化什么的,纯属算是题目要求,但是我想说一句,这是2017普及组的题目???相对而言算难的吧.......

7.单调队列优化(https://www.luogu.org/problem/P3089)

又是长见识的时间,单调队列我就不说了,现在我还只会手写队列,等到会用stl库再来写写这题吧。其实做完这题的时候我思考了这样一个问题,既然我dp都在找以前的最优值,那么什么时候可以用类似的算法,把以前的最优都处理一下,直接省掉一重循环(思考ing......)

8.DAG上的dp(https://www.luogu.org/problem/P2883)

一开始这题我连题目都看不懂的,看了题解还算是懂了那么一点(对于一个高考语文分数107即三年巅峰的人来讲,这种题目描述实属是难顶),其实这题我更想把它叫为递推,因为对于每个点直接加上连接点的值就好了,说是dp也无妨吧。

9.这题就想写一下,也没有什么算法和dp结合(https://www.luogu.org/problem/P1133)

这题给我的启发:当一层有后效性时,那就搞两层;两层不够就三层,三层不够.......

10.挺有意思的一个01背包(https://www.luogu.org/problem/P1417)

强烈建议刷过普通01背包的刷一下这题,长下见识。

我不知道以后我遇到dp题还能不能想的出来怎么写,但是这段刷dp的经历令我难忘。

往下一个专题进发——>线段树

谈谈我近一个半月的dp练习的更多相关文章

  1. MySQL查询近一个月的数据

    MySQL查询近一个月的数据 近一个月统计SQL select user_id, user_name, createtime from t_user where DATE_SUB(CURDATE(), ...

  2. python日志按天分割,保存近一个月日志,日志自动清理

    python日志按天分割,保存近一个月日志 import os import logging import re from logging.handlers import TimedRotatingF ...

  3. 来自多校的一个题——数位DP+卡位

    n<=1e9就要考虑倍增.矩阵乘法这种了 假设L=0 考虑枚举二进制下,所有X与R的LCP长度,前len高位 对于第len+1位,假设R的这一位是1 如果一个x的这一位是0了,那么后面可以随便填 ...

  4. HDU 5945 维护一个单调队列 dp

    Fxx and game Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Tot ...

  5. xubuntu14.04截图,彻底到Linux一个半月后记

        前言 自学计算机技术,越到后面,越依赖ubuntu,以致于很多时候都是一开机就打开虚拟机上的ubuntu10.04,Linux已经变得越来越重要了. 2014-04-17,ubuntu14.0 ...

  6. 学了近一个月的java web 感想

    对于每天学习的新知识进行一定的总结,是有必要的. 之前我学的每一门知识,我都没有怎么总结自己的问题,也没有怎么去想想该怎样才能学的更好,把知识掌握的更牢固.从现在开始呢,我会每半个月,或每一个月总结总 ...

  7. #umn 来美国近一个月的简单见闻

    时光如梭,到美国已经快要一个月了,从最初12+4飞行的劳累,到一开始每天吃了上顿没下顿的担心,到后来开始上课的不适,现如今生活已经基本步入了正轨,每天上上课写写作业,去rec center打打球健健身 ...

  8. 肝了一个半月的 Java 项目快速开发脚手架:Chewing

    前言 闲来无事,整一个 Java 项目快速开发脚手架. 正文 一.简介 Chewing 是一个简单的 Java 项目快速开发脚手架.既适合需要开发小型项目的小伙伴使用,也适合刚入门的新手用来学习一些常 ...

  9. D. Mysterious Present (看到的一个神奇的DP,也可以说是dfs)

    D. Mysterious Present time limit per test 2 seconds memory limit per test 64 megabytes input standar ...

随机推荐

  1. 小程序真机上报错 for developer: some selectors are not allowed in component wxss , including tag name selectors, id selectors, and attribute selectors

    for developer: some selectors are not allowed in component wxss , including tag name selectors, id s ...

  2. Java中遍历 Session 和 Request

    转: session的遍历: java.util.Enumeration e = request.getSession().getAttributeNames(); while( e.hasMoreE ...

  3. Java中null的判断

    Java中空指针的异常十分常见 if (name != null && !name.equals("")) { //do something } 或者 if (!& ...

  4. leetcode1305 All Elements in Two Binary Search Trees

    """ Given two binary search trees root1 and root2. Return a list containing all the i ...

  5. JAVA学习笔记-数组的三种初始化方式

      package Study; public class TestArray02 { public static void main(String[] args){//声明 int[] a; int ...

  6. “~" 的用法

    “~" 的用法 let arr = ['weixin','qq','weibo'] console.log(arr.indexOf('aa'),~arr.indexOf('aa'),'aa' ...

  7. C++面试常见问题——02动态分配内存

    动态分配内存 C++动态内存 C++程序中内存分为两个部分 堆:程序中未使用的内存,在程序运行时可用于动态分配内存. 栈:函数内部申明的所有变量都将占用栈内存. 很多时候不知道一个程序到底需要多少内存 ...

  8. 11.json

    import json # json反序列化 # json_str = '{"name":"qiyue","age":18}' # stud ...

  9. 三十一、SAP中的循环和判断图标和表格的混用

    一.代码如下 二.显示结果如下

  10. 016-PHP读取文件常见属性

    <?php print("文件的所有者(UID 值):"); print(fileowner("data.txt") . "<br> ...