
(算法+例题)讲解
ZZZWWWFFF_
这个作者很懒,什么都没留下…
展开
-
合并石子(动态规划)
首先理解题意,笔者看到这道题时首先想到的是贪心,仔细分析后发现题上没说石子根据一定顺序来摆放,易证局部最优解不一定是问题最优解,没有贪心性质,不能用贪心。现在一共有三堆石头,每堆石子的数量分别是3,4,11。那么从i到j的所有花费都可以表示出来了,取一个使得dp[i][j]最小的值。最后用一个二维数组dp[i][j]表示从第i堆到第j堆石头合并的最小分数。输入4 5 9 4,还要考虑4 4 5 9,9 4 4 5和5 9 4 4。易看出先合并前两堆的石子的花费比较小,不同的合并方式会造成不同的得分。原创 2023-04-27 21:18:13 · 776 阅读 · 0 评论 -
括号匹配II(动态规划)
( [ ( ] 观察这个例子,我们按照该题的题意,我们可以很容易想到这个例子只需添加两个右括号即可满足题意,但是按照栈的做法,我们我们会发现得到的结果是4,因为按照栈的逻辑没有办法使得两个[ ]是得到匹配的,因此答案里多了2。那么如果下标为i和下标为j的括号是匹配的话,那么我们的当前问题就可以转换成dp[ i ][ j ]=dp[ i +1 ][ j - 1]首先需要理解的是该题与原先我们使用栈做的括号匹配有什么区别。内的区间进行遍历分割,如果有更小的值,就采用更小的,也即。([])[]是匹配的。原创 2023-04-27 11:40:06 · 392 阅读 · 0 评论 -
方块堆塔(记忆化搜索)
各个立方体 “能否被摞”关系是一个典型的二元关系,二元关系可以用图来建模,如果b能摞在a上,a到b就有一条有边向,所以这就是一个DAG,所要求的便是DAG上的最长路径。首先先理解清楚题意,给定n个立方体,求最高叠多高,这里主要注意的是,每一个立方体的堆叠方式都有3种(分别以三条棱长作为高)然后对每个立方体而言,枚举每个立方体,如果能够叠上某个立方体,就叠上同时用dp数组记录子问题即可。然后对该图,我们利用记忆化搜索求出最长路径即可。该题属于动态规划练习题。原创 2023-04-16 14:40:00 · 992 阅读 · 0 评论 -
矩阵链相乘的乘法次数(动态规划)
我们先定义一个数组来存储子问题,这里dp[i][j]定义为矩阵[i,j]相乘的最小总次数(其中1原创 2023-04-15 11:41:50 · 1378 阅读 · 0 评论 -
最长公共子序列(动态规划)
先定义子问题的存储数组,按照题目问题定义即可,很明显子问题肯定是被限制在两个输入字符串a和b各自的子字符串里,因此我们定义一个二维数组dp[i][j] 为对a的子字符串[1,i] 和 对b的子字符串[1,j] 的最长公共子序列长度。,zk} 是X={x1,x2,…,xm} 和 Y={y1,y2,…,yn} 的最长公共子序列。那么Zk-1是Xm-1和Yn的最长公共子序列。那么Zk-1是Xm和Yn-1的最长公共子序列。那么Zk-1是Xm-1和Yn-1的最长公共子序列。1)如果zk = xm = yn。原创 2023-04-13 15:25:57 · 507 阅读 · 0 评论 -
最长上升子序列(动态规划/贪心)
根据题意,我们需要得到最长的上升子序列,那么怎样才能得到最长呢,肯定每一个数字越小越长嘛,因此我们定义一个数组来存储最长的上升子序列,每次从输入数组中读入元素ele,如果说ele大于已经得到的子序列的最大元素,则直接加入即可,反之,我们从子序列中找到第一个大于ele的元素并将其替换为ele(选择使用二分查找)对于该题而言,我们首先需要一个数组来记录子问题的解(一般题目问什么,数组的定义按照问题来定义即可),这里我们定义一维数组dp[i]为到下标为i的元素前的最长上升子序列长度为dp[i]原创 2023-04-13 14:24:21 · 743 阅读 · 0 评论 -
扑克牌(递推)
该题框架很容易写出来,循环对每一个计算发个他Ai张牌有多少种组合数,然后牌数减去发出的牌数即可,难点主要在于计算组合数。即利用a[i][j]=a[i-1][j-1]+a[i-1][j]这里我们考虑使用杨辉三角来求组合数。原创 2023-04-05 20:59:34 · 121 阅读 · 0 评论 -
最大食物链计数(记忆化搜索/拓扑排序)
根据题意我们不难理解该题的意思就是求出一个图中的食物链一共有多少条,而我们知道食物链的起点是生产者不会捕食其他生物,终点时不会被捕食的捕食者,仔细想我们会发现,生产者的入度为0,而不会被捕食的捕食者的出度为0,从入度为0的点开始,这不是拓扑排序的特点吗,因此考虑使用拓扑排序。如上图所示,以蓝色点为起点,红色点为终点,我们不难发现,到达红色点路径数取决于到达与之相连的2、3、4点,而到达它们的路径数又取决于与之相连的点,以此类推。第二轮:删除 2 号点,2 号点可以到的点(3 号点、5 号红色点)都加 1。原创 2023-04-05 19:48:46 · 667 阅读 · 0 评论 -
旅行计划(拓扑排序)
首先我们需要确定起点,即最先到达的城市,因为我们希望经过的城市数量最多,因此考虑从最西边出发,即入度为0的顶点出发,到这里容易想到使用拓扑排序解答。对于每个顶点,我们定义一个ans数组记录以i点为终点时经过的最大城市数,不难发现。跑完一遍拓扑排序,答案也就出来了。原创 2023-04-05 16:00:41 · 118 阅读 · 0 评论 -
营救(最短路径/生成树)
第一感觉该题可以使用最短路径的dijkstra解决,我们将原本dijkstra中的dis[i]数组的含义改为从起点到i点的最大拥挤度,然后因为会遍历到不同的路径,因此我们在遍历的过程中更新dis数组,即对应上面的在最大值中找最小值。看完题意,这里要注意理解我们的目的是求出在所有 能从起点到终点的每一条路径中拥挤度的最大值中得到一个最小值,例如上面的样例就是从1到3存在两条路径,一条路径中的拥挤度最大值为3,一条为2,因此输出2。原创 2023-04-02 17:20:50 · 177 阅读 · 0 评论 -
请柬(最短路)
该题根据题意很明显属于最短路径的题目,因此该题我们选择使用dijkstra,这里容易得到的是从起点到其他点的最短路径,只需跑一边dijkstra得到dis数组后将结果叠加即可,主要的问题是因为我们还需要加上返程的费用,即我们需要得到其他点到起点的最短路径并叠加,我们应该怎么做呢?原创 2023-04-02 16:01:05 · 107 阅读 · 0 评论 -
路径计数2(递推)
此时我们最直观的认识是设置障碍点到达的路径数为0就好了,实际上,不止是这样,如果障碍出现在边界上,而我们只是单单设置障碍点为0的话是不够的,因为此时边界上在障碍点之后的点都会被阻碍到而不能一种到达,所以在边界上直到障碍点出现前才能正常初始化为1。该题是做过的一道题的改版,在没有障碍的情况下,我们的递推方程较为容易得到,就是每一个点的路径数=到达该点左边的路径数+到达该点上边的路径数,因为我们在每一个点只能向下或者向右走,然后初始化左边界和上边界到达的路径数都是1即可。那么出现障碍之后会有什么问题呢?原创 2023-04-02 12:15:56 · 206 阅读 · 0 评论 -
[蓝桥杯 2022 省 B] 统计子矩阵
下面我是利用了一点前缀和的思想进行处理,我枚举所有的点作为起点去求出所有可能的前缀和数组,然后每一个前缀和都是我们可能的矩阵,因此判断对应数组的值是否满足题意即可。即枚举所有可能的子矩阵,然后对符合要求的矩阵进行计数即可。该题第一思路是暴力解决。原创 2023-04-01 15:08:14 · 181 阅读 · 0 评论 -
小浩的幂次运算(快速幂)
我们可以对两边同时取对数,这样就可以得到对应的指数是多少,这里可以利用cmath库函数log()进行对数计算,只需进行简单的对数转换即可,例如log(8)/log(2)=log2(8)=3。看到该题庞大的数据量以及幂运算,很明显,我们需要使用快速幂解决。值得注意的是因为这里利用了除法,因此还需要注意分母为0的情况。原创 2023-04-01 13:58:32 · 131 阅读 · 0 评论 -
循环赛日程表(分治/暴力)
其中左上角与左下角的两小块分别为选手1至选手4和选手5至选手8前3天的比赛日程。因为前四位选手在前四天已经与其对手打过了,所以他们的对手不可能在出现在前四天,据此,将左上角小块中的所有数字按其相对位置抄到右下角,同理后四位选手在前四天的对手只可能出现在前四位选手的后四天比赛中,所以又将左下角小块中的所有数字按其相对位置抄到右上角,这样我们就分别安排好了选手1至选手4和选手5至选手8在后4天的比赛日程。按分治策略,我们可以将所有的选手分为两半,则n个选手的比赛日程表可以通过n/2个选手的比赛日程表来决定。原创 2023-03-29 21:04:15 · 881 阅读 · 1 评论 -
斐波那契数列第n项Plus(快速幂应用)
这样我们实际上就只需计算矩阵A的n-1次方就可以得到Fn了,此时答案就是矩阵A的n-1次方的第一行数相加。利用上图公式,我们可以对某一矩阵进行降幂操作。首先我们需要一些线性代数的知识。该题属于矩阵快速幂的经典应用。原创 2023-03-29 19:56:17 · 743 阅读 · 0 评论 -
幂运算(快速幂)
所谓的快速幂就是通过降低我们连乘的次数来达到的,例如我们考虑计算2^10,按照正常一个一个连乘我们需要10次运算,但是如果我们将底数变大而指数变小呢?如2^10=4^5,这样我们就只需要5次运算了,当然还可以继续优化,此时的指数变成了5,我们不能再像刚刚那样直接底数平方了,因此,我们考虑将其中一个底数提出来就变成4^5=4*4^4,此时对4^4再重复刚刚的降指数操作了,到这里我们便可以写代码了。因此我们介绍使用快速幂解决。原创 2023-03-29 19:18:22 · 195 阅读 · 0 评论 -
很大的数组的第k小(快速排序)
我们知道快速排序每次都会选定一个 对照值 然后进行分区,然后将比对照值小的数放到对照值的左边,将比对照值大的数放到对照值的右边,此后该对照值的位置就不会再改变了。如果我们得到的index+1>k的话,则该对照值必然不会是第K小的数,当然,在该对照值右边的就更加不是了,因此我们可以将范围缩小到该对照值的左边。如果我们得到的index+1原创 2023-03-29 19:06:41 · 1080 阅读 · 0 评论 -
A*B Problem(模拟)
思路上比较简单,模拟小学乘法即可。需要注意的事项都在注释中。原创 2023-03-28 16:30:21 · 135 阅读 · 0 评论 -
A+B Problem(模拟)
思路比较简单,模拟小学加法即可,这里需要注意的是a与b相加之后的数的长度可能是a+b+1。原创 2023-03-28 15:28:03 · 122 阅读 · 0 评论 -
最大子段和(分治)
主要的思路还是使用分治的思想,即将数组一次又一次地分成两个数组来求最大子段和,而最小的情况就是当分成只剩1个元素时,最大子段和就是该元素本身,此外,往上走一层,当分成只剩两个元素时,我们发现可以得到左右两边的最大子数组都可以得到,因此比较取最大值即可,是不是这样就好了呢?例如当剩下两个元素1,1 此时左右最大子段和分别是1和1,但是实际上应该是2,也就是说,我们实际上忽略了一种情况:最大子段和在中间的情况,因此我们还需要计算中间的子段和与左右子段和比较取最大值即可。这里介绍使用分治算法进行解答。原创 2023-03-28 15:09:12 · 315 阅读 · 0 评论 -
【CSGRound1】天下第一(记忆化搜索)
即我们可以使用一个记忆数组s[x][y]记录下在出现x和y时最后是谁赢了,这样下次再碰见x和y就可以直接在数组里找到答案了,同时我们通过在纸上模拟样例1发现,在出现平局时必然会存在一个死循环即会回到开始的x和y,因此我们只需假设起点s【x】【y】=-1,那么再次出现x和y时判断即可返回平局的结果。该题第一思路是直接使用搜索解决,即使用dfs模拟整个游戏的过程,对于判断是否平局则通过回合数进行判断,这里我暴力选择如果回合数>10000则判定为平局。实际上该题还可以使用记忆化数组进行优化。原创 2023-03-22 21:26:16 · 89 阅读 · 0 评论 -
[USACO04NOV]Apple Catching G(记忆化搜索)
该题第一思路是使用搜索枚举所有可能的情况,最后取最大值即可。即使用一个记忆数组来存储某种情况下奶牛能得到的最大苹果数。但是由于该题数据量的限制,并不能通过所有样例。因此我们考虑使用记忆化搜索进行优化。原创 2023-03-22 20:35:01 · 238 阅读 · 0 评论 -
Function(记忆化搜索)
该题第一思路就是直接根据所给条件写出各种情况下的递归即可,但是题目实际上暗示了,该题并不能这样做,会超时,因此我们尝试使用记忆化搜索进行优化,通过观察我们不难发现,在输入的a,b,c中实际上最大计算不会超过w(20,20,20),并且如果存在负数的话,就直接返回1,因此我们的记忆数组并不需要开太大。原创 2023-03-22 11:41:04 · 176 阅读 · 0 评论 -
[SHOI2002] 滑雪(记忆化搜索)
该题思路上很容易想到使用搜索进行解决,只需遍历每一个点作为起点进行搜索,对能够到达的最远距离进行计算,最后对每一个搜索得到的距离取最大值即可。但是这样的方法实际上还可以进行一些有效的优化。这里我们尝试使用记忆化搜索。原创 2023-03-21 20:22:34 · 157 阅读 · 0 评论 -
逆序对(归并排序)
首先我们知道,归并排序在每一次合并的时候,前后两个序列都是已经排好序的,例如在某个时候。第一思路是使用嵌套for循环进行解决,即枚举每一个数字后面比他小的数字并且进行计数,注意的是该题提示使用较快的输入,因此我们选择使用scanf输入。这里提供一种思路:利用归并排序的归并进行解答。右区间: 1 2 9 下标为j。但是对于该题的数据范围而言并不能完美解决。存在左区间:5 6 7 下标为i。据此,我们就可以完成代码的编写了。因此我们需要更好的思路。原创 2023-03-21 17:19:57 · 217 阅读 · 0 评论 -
浅析01背包问题
2:f(i,j)= max(f(i-1,j),f(i-1,j-w[i])+ v[i]) 此时面对i商品,我们可以选择将其收入囊中,也可以选择不要它,此时我们取最好情况即可。f(i-1,j-w[i])+ v[i])表示在i-1个其他商品中剩余容量为j-w[i]的最大价值加上我们刚刚拿下的v[i]1:f(i,j)= f(i-1,j) 此时我们不取i商品,所以直接去找前 i-1个其他商品。我想知道在物品总重不超过背包容量的情况下,我们能取得的最大总价值是多少?1:包的容量不够装该商品了。原创 2023-03-21 15:21:23 · 236 阅读 · 0 评论 -
[蓝桥杯 2017 省 B] k 倍区间(前缀和+优化)
根据上面的介绍,我们知道假设有m个前缀和满足除以K的余数相同,那么任意两个前缀和的差都能被K整除,所以K倍区间的个数就是,即m*(m-1)/2个。第一思路容易想到用前缀和数组,然后枚举可能出现的所有区间,对满足k倍区间的区间进行计数即可。我们将所有的前缀和sum[i]全部模上K,统计所有相同余数的个数。不过对于该题的数据范围而言,O(n^2)的时间复杂度必然不够。那么应该怎么优化呢?记得开long long。原创 2023-03-18 14:11:26 · 1176 阅读 · 3 评论 -
[蓝桥杯 2022 省 B] 扫雷(搜索)
即将当前节点先初始化为排雷火箭,然后遍历所有还未被引爆的地雷,如果某个地雷被当前地雷引爆了,就做个标记,同时将其作为下一节点。下面是使用栈去模拟这个过程的代码,本质上与DFS大差不差。第一思路比较容易想到的是使用搜索或者去模拟爆炸的过程。但是该方法时间复杂度为O(mn)只能拿到40分。原创 2023-03-16 12:13:36 · 351 阅读 · 0 评论 -
[蓝桥杯 2013 省 A] 大臣的旅费(树形DP/dijkstra)
根据题意我们易知只要x取得最大即可得到最大花费路费,因此该题便转换成求最大路径的问题了,下面我们选择使用堆优化的dijkstra进行解答(这里可以在存图时将所有权值变成负数,这样还是套用求最小路径的模板,但是却能用来求最大路径啦)该题依题意可以很容易判断出所给图是一颗最小生成树,不过下面这种做法与其没有太大关系。注意该算法不能通过所有样例。原创 2023-03-14 16:49:22 · 154 阅读 · 0 评论 -
不成熟的梦想家 (未熟 DREAMER)(差分)
该题题意上很明显出现了对一个一维数组的某一段区间加上某一个数的操作,容易想到使用差分解决(并且题目中计算魅力值的公式也暗示了差分的使用)值得注意的问题是,题目也强调可能需要使用longlong,记得用longlong。因此套用差分模板,然后计算魅力值即可。原创 2023-03-14 15:11:56 · 155 阅读 · 0 评论 -
[蓝桥杯 2017 国 C] 小数第 n 位(模拟/数论)
该题第一想法是想直接使用double进行数据的存储然后直接输出,实际上看到该题的数据范围就可以排除该方法了,double的精度根本不够!第二思路是想到去模拟除法的计算,只需不断地对a与b进行除法计算和取模计算即可(这点读者可以自行在纸上尝试)但是上面的代码在面对n特别大的时候会存在超时的情况,因此我们需要进行优化!这里我们利用数学知识进行优化,尽量地减少我们模拟的次数。原创 2023-03-11 12:28:56 · 184 阅读 · 0 评论 -
[蓝桥杯 2020 省 A1] 分配口罩
思路比较容易想到,因为口罩全部只有15批,因此直接暴力dfs搜索即可。原创 2023-03-09 19:01:54 · 203 阅读 · 0 评论 -
[蓝桥杯 2020 省 A1] 合并检测
下面我们以100个民众为例,分别计算k取不同值时所需的试剂盒总数。该题我的思路是枚举大部分可能的K,最后选出最小的那个即可。原创 2023-03-09 18:52:28 · 190 阅读 · 0 评论 -
[蓝桥杯 2020 省 A1] 跑步训练(模拟)
容易想到可以用每两分钟作为一个单位进行计算,但是认真重新思考,发现其实不然,因为可能你的体力只剩下400,此时体力>=300,按照上面的思路即分钟++,但是其实此时体力已经不足以支撑需要先消耗的600了,因此该思路是错误的。正确思路应该是在体力>600时去模拟跑步的过程,而体力原创 2023-03-09 18:42:35 · 216 阅读 · 0 评论 -
[蓝桥杯 2017 国 B] 发现环 (拓扑排序)
题目的意思还是比较好理解的,主要是涉及到图中环的判断问题。下面这里我使用的是拓扑排序进行解答。这里忘记的同学可以参考。原创 2023-03-08 20:40:23 · 245 阅读 · 0 评论 -
[蓝桥杯 2017 国 C] 合根植物 (并查集)
该题一眼并查集,直接套并查集模板即可。原创 2023-03-08 19:51:05 · 137 阅读 · 0 评论 -
[蓝桥杯 2022 省 B] 统计子矩阵 (前缀和)
这里假设以(1,1)点为起点求可能的所有子矩阵的和,我们定义一个数组temp[i][j]的值为(i,j)这个点到起点(x,y)所连成线的矩阵的权值(即矩阵内每个点的和),这里可以利用动态规划的思想,我们可以很容易想到tmep[i][j]=temp[i-1][j]+temp[i][j-1]-temp[i-1][j-1]容易知道这样的算法是时间复杂度是n^4的,不过该题的数据范围并不太大,因此还是能通过大部分样例。根据上面的思想,我们再枚举每一个点作为起点即可枚举出所有情况。注意要保证数组不要越界。原创 2023-03-08 19:14:27 · 410 阅读 · 0 评论 -
[蓝桥杯 2022 省 B] X 进制减法(贪心)
即理解:X进制数321为什么等于十进制数65?(其中3的进制为八进制,2的进制为十进制,1的进制为2进制)我们只需要在保证进制合法的情况下使得所有进制最小即可。明白了这一点其实就不难想到如何使得A-B最小。类比正常的进制数计算我们可以得到。该题首先关键的一点是理解题意。据此就可以写出代码了。原创 2023-03-07 15:33:34 · 1379 阅读 · 3 评论 -
城邦(最小生成树应用)
该题翻译过来就是:给定2021个顶点,请你使用2020条边将所有顶点进行连接,保证任意两个顶点之间可以有路径到达,同时保证使用边的权值之和最小。即先计算所有边的权值同时将它们保存在一个数组中对边的权值进行从小到大排序,然后从小到大选出边连接两个顶点,这里利用并查集实现判断是否形成回路。看到这里,如果你对最小生成树熟悉的话,那么不难想到该题是最小生成树的一道应用题。这里我选择使用克鲁斯卡尔算法进行解答。该题主要注意先好好理解题意。原创 2023-03-05 15:54:09 · 101 阅读 · 0 评论