谈谈我近一个半月的dp练习
前请提示: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练习的更多相关文章
- MySQL查询近一个月的数据
MySQL查询近一个月的数据 近一个月统计SQL select user_id, user_name, createtime from t_user where DATE_SUB(CURDATE(), ...
- python日志按天分割,保存近一个月日志,日志自动清理
python日志按天分割,保存近一个月日志 import os import logging import re from logging.handlers import TimedRotatingF ...
- 来自多校的一个题——数位DP+卡位
n<=1e9就要考虑倍增.矩阵乘法这种了 假设L=0 考虑枚举二进制下,所有X与R的LCP长度,前len高位 对于第len+1位,假设R的这一位是1 如果一个x的这一位是0了,那么后面可以随便填 ...
- HDU 5945 维护一个单调队列 dp
Fxx and game Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Tot ...
- xubuntu14.04截图,彻底到Linux一个半月后记
前言 自学计算机技术,越到后面,越依赖ubuntu,以致于很多时候都是一开机就打开虚拟机上的ubuntu10.04,Linux已经变得越来越重要了. 2014-04-17,ubuntu14.0 ...
- 学了近一个月的java web 感想
对于每天学习的新知识进行一定的总结,是有必要的. 之前我学的每一门知识,我都没有怎么总结自己的问题,也没有怎么去想想该怎样才能学的更好,把知识掌握的更牢固.从现在开始呢,我会每半个月,或每一个月总结总 ...
- #umn 来美国近一个月的简单见闻
时光如梭,到美国已经快要一个月了,从最初12+4飞行的劳累,到一开始每天吃了上顿没下顿的担心,到后来开始上课的不适,现如今生活已经基本步入了正轨,每天上上课写写作业,去rec center打打球健健身 ...
- 肝了一个半月的 Java 项目快速开发脚手架:Chewing
前言 闲来无事,整一个 Java 项目快速开发脚手架. 正文 一.简介 Chewing 是一个简单的 Java 项目快速开发脚手架.既适合需要开发小型项目的小伙伴使用,也适合刚入门的新手用来学习一些常 ...
- D. Mysterious Present (看到的一个神奇的DP,也可以说是dfs)
D. Mysterious Present time limit per test 2 seconds memory limit per test 64 megabytes input standar ...
随机推荐
- Day8 - C - Another Problem on Strings CodeForces - 165C
A string is binary, if it consists only of characters "0" and "1". String v is a ...
- 收藏!阿里云maven镜像配置文件
<?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Soft ...
- windows上使用git
开始的时候同事只给了一个地址,类似这样:git@111.111.1.1:ABCDEF (1)如何在Windows上使用Git 有一篇博客不错:http://www.tuicool.com/articl ...
- C++ 语言程序设计(清华大学)1
1.回文数字判断方法(逆过来数值相等):y=y*10+x%10; x /= 10; return(x==y) 2.int rand(void)函数,所需头文件<cstdlib> ,功能是求 ...
- 树莓派 Raspberry 软件源更改 看门狗启用
看门狗无法在pi1上执行,似乎后更高级的pi上面才可用 1.替换脚本 下面脚本请直接复制到终端执行!! 适用于raspbian-stretch(基于Debian9) sudo -s echo -e & ...
- face_recognition人脸识别
对亚洲人识别准确度有点差,具体安装移步:https://www.cnblogs.com/ckAng/p/10981025.html 更多操作移步:https://github.com/ageitgey ...
- JAVA DateUtil 工具类封装(转)
原文链接 https://blog.csdn.net/wangpeng047/article/details/8295623 作者三次整理后的代码 下载链接 https://www.lanzou ...
- CentOS 6.5(x86_32)下安装Oracle 10g R2
一.硬件要求 1.内存 & swap Minimum: 1 GB of RAMRecommended: 2 GB of RAM or more 检查内存情况 # grep MemTotal / ...
- c++程序—选择结构
if(判断条件){执行语句} #include<iostream> using namespace std; #include<string> int main() { ; c ...
- P1042 字符统计
P1042 字符统计 转跳点: