![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
紫书后的进阶学习
文章平均质量分 71
紫书的学习告一段落,后面即是对题目的熟悉,我蓝书找不到了,现在先对进阶那本书进行学习。
酉鬼2333
摆摆
展开
-
7.5 数位DP
7.5 数位DP所谓数位DP,就是某些问题如果以数作为状态的属性进行转移,数值过大会导致时间和空间的复杂度过高。然而问题中n位数的情况可以由i位数(1<=i<n)的情况直接得到,于是我们可以以数的长度和数某位的值作为状态的属性进行转移。下面以一道题为例。hdu 2089 “不要62”一个数字,如果包含4或者62,它是不吉利的。给定m和n,统计m~n中吉利数的个数。分析:如果直接用dp[i]表示1-i,当n的值过大时显然复杂度太高。考虑用数位dp,对于长度为i的符合条件的数,在它的首位原创 2021-12-07 13:39:49 · 113 阅读 · 0 评论 -
7.3 区间DP
7.3 区间DP紫书中的最佳矩阵链乘问题和最佳三角剖分问题就是区间DP问题,区间DP和之前基础DP的区别就在于(我个人理解):基础DP状态与状态之间的关系往往是线性的,第i+1个状态可以由第i个状态得到。二维线性DP中,第i行第j列的状态往往由第i行第j-1列的状态,或第i-1行第j列的状态,或第i-1行第j列的状态与第i行第j-1列的状态共同得到。区间DP的状态(i,j)往往不是指一个结点,而是指一段端点为i和j的区间。在解题中,先解决小区间的问题,再合并小区间得到更大区间问题的结果,直到解决最后的原创 2021-12-01 11:09:41 · 323 阅读 · 0 评论 -
7.2 递推与记忆化搜索
7.2 递推与记忆化搜索记忆化搜索就是DP过程中的一种小手段,往往能够减少非常多的重复计算。poj 1163 “The Triangle”给定一个n层的三角形数塔,从顶部第一个数往下走,每层经过一个数字,直到最底层。注意,只能走斜下方的左边一个数或者右边一个数。问所有可能走到的路径,最大的数字和是多少?分析:这个问题就是紫书上dp部分作为序章的数字三角形。如果像下面这样常规的递归写法:int solve(int i,int j){ return a[i][j]+(i==n?0:max(solv原创 2021-11-29 12:56:15 · 261 阅读 · 0 评论 -
7.1 基础DP
7.1 基础DPDP在紫书那里也有一个单章介绍这个专项,不过当时并没有正式的介绍DP思想而是从例题直接入手的,黑书这里从基础开始一步一步讲解。首先DP和贪心,分治法一样,DP并不指一个特定的算法,而是一种解决问题的算法思想,简单解释来说是将一个复杂的问题分割成相对简单的子问题,再一个个解决,最后得到复杂问题的最优解。与分治法不同的是,分治法的子问题之间互相独立,每个子问题能够独立解决。DP的子问题,之间互相联系,最终解即是子问题的其中之一。7.1.1 硬币问题有n种硬币,面值分别为v1,v2··原创 2021-11-28 22:37:56 · 489 阅读 · 0 评论 -
5.4 树状数组
5.4 树状数组树状数组我个人理解上就是能够解决线段树的一部分问题的一个简化版本的线段树,通过二进制的一些运算进行查询和更新。树状数组的概念假设对于长度为n的数列{a1,a2······an},有如下两种操作:1.修改元素add(k,x):2.求和sum(x):求a1到ax的和(ai到aj的和可以用两个sum值相减)。树状数组的代码如下:...原创 2021-11-17 19:29:21 · 326 阅读 · 0 评论 -
5.3 线段树
5.3 线段树如雷贯耳的一种数据结构。主要用于优化反复对序列某段区间进行运算求值和修改区间内点的值的问题的时间复杂度。5.3.1 线段树的概念线段树是用于处理区间问题的数据结构,其中每个结点代表一段区间[L,R] (一条线段),下图即是线段[1,10]的线段树结构。对于每个结点[L,R]:1.L=R,说明这个区间内只有一个点,它就是叶结点。2.L<R,说明这个区间内至少有两个点,同时这个区间可以被对折分成两个子节点,左子节点对应的区间为[L,M],右子节点对应的区间为[M+1,R],其原创 2021-11-15 22:13:06 · 555 阅读 · 0 评论 -
5.2 二叉树
5.2 二叉树比起紫书上二叉树的基础知识,黑书拓展了一些特殊的树形结构。5.2.1 二叉树的存储二叉树的基本概念就不再多做介绍,对一些用语不太明白的详见紫书6.3 树和二叉树。关于二叉树的存储结构,一般用指针来实现:struct node{int value; node *l,*r;}l和r分别指向当前结点的左孩子和右孩子,当新建一个node时用new来申请内存,使用完毕时,用delete进行删除。二叉树的遍历主要就是两种遍历方式,宽度优先遍历和深度优先遍历。宽度优先遍历紫书中的遍原创 2021-11-03 17:18:44 · 242 阅读 · 0 评论 -
5.1 并查集
5.1 并查集并查集是一种精巧且实用的数据结构,主要用于处理一些不相交集合的合并问题。如果还记得紫书十一章内容的同学,这个概念肯定不是第一次见了,在讲解Kruskal算法时就已经简单介绍过这种数据结构:其中图上的结点分割成一个一个不相交的点集合,并查集将一个集合中的点用一种类似于链表(递归)的方法存储着,集合中的点不存在次序关系,只存在是否属于某个“帮派”的属性,优势就在于两个集合的合并就像链表的插入一样非常之快。当时也提到了并查集可能遇到的特殊情况:树退化成一条长链子从而降低查找速度。解决的方法是在遍原创 2021-10-25 19:11:05 · 272 阅读 · 0 评论 -
4.4 DFS
4.4 DFS黑书的这一章节和上一章节一样汇总了DFS部分的知识和内容。4.4.1 DFS和递归上一章已经介绍过了BFS和DFS两种算法思想,我们这里就直接看hdu1312使用DFS的解法。void DFS(int dx,int dy){room[dx][dy]='#'; num++;//标记已经搜索过的区域防止重复遍历 for (int i=0;i<4;i++){int newx=dx+dir[i][0],newy=dy+dir[i][0];//向四个方向进行深搜 if (CH原创 2021-10-20 21:40:24 · 182 阅读 · 0 评论 -
4.3 BFS
4.3 BFS紫书那里我们当时是先学习的二叉树的BFS,再学的简单图的BFS,最后往更深入的学习回溯,路劲寻找问题和A*算法,IDA*算法,黑书这里将这些汇总了起来放在一章节进行介绍(只是希望不要像上上章那么坑就好)。4.3.1 BFS和队列首先要知道BFS(广度优先搜索)和DFS(深度优先搜索)都是最基本的两大暴力搜索技术,常用于解决最简单的图和树的遍历问题。那么如何区分和理解两种算法呢?我们以老鼠走迷宫为例,有两种不同的方法:1.一只老鼠走迷宫。它在每个路口都选择先走某个固定的方向,直到碰壁无原创 2021-10-11 13:13:37 · 161 阅读 · 0 评论 -
4.2 子集生成和组合问题
4.2 子集生成和组合问题简单叙述一下,就是求n个元素的集合的所有子集。紫书这里提供了三种不同的写法:增量构造法,位向量法和二进制法(我清晰地记得这篇是520那天写的)。其中常用的是增量构造法和二进制法,增量构造法写起来和理解起来比较苦难,但是时间效率高。#include<stdio.h>//根据前面的经验我们显然可以知道这里的算法是通过递归实现的 void print_subset(int n,int* A,int cur){//说实话这里的cur我个人觉得写作len记作当前子集长原创 2021-10-07 21:28:08 · 93 阅读 · 0 评论 -
4.1 递归和排列
4.1 递归和排列递归emmm,老生常谈了,不过还要重申一个非常重要的问题即是:常规的递归实际上没有降低算法的复杂度,只是简化了代码而已。接下来看看黑书提出的3个问题。问题 4.1打印n个数的全排列。分析:用stl里面的next_permutation遍历一遍的方法就不再提了,上一章节已经用过一道例题进行说明了,至于递归的方法emmm,紫书上面提供过一种做法:#include<cstdio>#include<algorithm> using namespace st原创 2021-10-06 23:52:34 · 105 阅读 · 0 评论 -
3.3 next_permutation()
3.3 next_permutation()这个函数在紫书全排列那章节提过几句,但提的不多。这个函数的主要作用就是根据给定的排列求出字典序中它的下一个排列。需要注意的是,和书上说的不同,如果是最后一个排列访问它的下一个排列,我们得到的是整个全排列的第一个排列。具体的实操应用直接看书上的例题吧。hdu 1027 “Ignatius and the Princess Ⅱ”给定1-n,要求输出字典序第m小的序列。分析:1-n的全排列字典序最小的即是1,2,3·····n,即从这个排列一直向下next_p原创 2021-10-06 21:09:04 · 96 阅读 · 0 评论 -
3.2 sort()
3.2 sort()其实就是对sort()这个工具进行了介绍,有关紫书sort的部分在第四章函数那里,这里带大家简单地回顾一下。首先基本格式:sort(指针(迭代器)1,指针(迭代器)2,cmp函数)就是对两个指向之间的元素进行排序,具体的区间为:[first,last)。cmp函数表示比较函数,即排序后的序列元素与元素之间应当遵循的规则,如果不加,就默认按照从小到大的顺序进行排序。cmp函数的写法和优先队列那里的·····,不大一样(至少我习惯的写法不太一样),优先队列那里是像下面一样写一个结原创 2021-10-06 07:23:22 · 78 阅读 · 0 评论 -
3.1 容器
3.1 容器前两章都是一些介绍过的概念,我们直接从第三章开始进行学习。这里的容器指的主要就是STL容器,STL容器主要分为顺序式容器和关联式容器。顺序式容器包括vector,list,deque,queue,prioritiy_queue,stack等:vector:动态数组,即不定长数组,能从末尾进行快速的插入和删除(也仅能从末尾),同时满足数组的特性——根据索引直接访问元素。list:双链表queue:队列,FIFOdeque:双端队列,比起传统队列,可以从前面或后面快速插入与删除,并且直原创 2021-10-06 01:01:56 · 94 阅读 · 0 评论 -
黑书学习日志
学习目标:对ACM算法竞赛进阶的篇章进行学习学习内容:学习时间:须知:学习内容:主要就是围绕算法竞赛入门到进阶展开学习的(标出来的内容都是我感觉比较重要的或者说必须要了解的)黑书(看过我紫书专栏的都知道这里就相当于一个目录):学习时间:一些空余时间须知:1.首先这个博客是我自己写的用来娱乐和复习,所以描述语言用的都不是非常专业,有些地方甚至会有问题,欢迎大家前来沟通交流。2.由于是学习算法,所以我用的是 Dev-C++ 5.11,CV的时候请务必注意自己使用的编译器和环境哦3.因为是自己原创 2021-10-02 15:12:45 · 134 阅读 · 0 评论