随笔分类 - 搜索
摘要:Description 给定一个环形的01序列,保证任意相邻的m个值中有不超过k个1,求满足要求的方案数对1e9+7取模的值 Solution 状压dp+矩阵快速幂 由于m的范围很小,所以我们考虑状压dp存储状态,而由于n很大,所以我们考虑矩阵快速幂优化转移 我们定义$f(i,j)$表示前i个数最后
阅读全文
摘要:Solution 由于搜索量较大,我们采用IDA*算法求解。 按照迭代加深搜索的基本方法,我们限制搜索深度,然后寻找在当前限制下是否存在解。 为了提高算法效率,我们设计A*函数作为估价,返回目标位置与实际不同的个数即可。 在搜索时我们不妨记录上一步搜索的分支,以免执行上一次操作的逆操作。 本题难点主
阅读全文
摘要:Description 制作一个m层,体积为n的蛋糕,每层都是一个圆柱体,且下面的圆柱体的半径和高度必须大于上面的,求一种方案使得表面积最小(表面积不含底面积) Solution 搜索题,我们考虑如下优化(假定当前搜索到第i层,已经用了体积v,表面积s): Code 1 #include <bits
阅读全文
摘要:Description 给定整数n,构造一个递增的正整数序列使得a1=1,am=n,且对于任意的k(1≤k≤m)都存在ak=ai+aj,最小化序列的长度(即最小化m) Solution 由于n规模较小,所以我们可以采用迭代加深搜索来求解答案,即固定搜索的深度(序列的长度),搜索答案,若搜索不到答案则
阅读全文
摘要:Description 给定一张无向图,求两点之间次短路的长度 Solution 关于用A*算法求解k短路,在此不再赘述,相关内容请见这里。 这里主要讲述一个坑点,本题是无向图(与POJ2449不同),我们在A*扩展节点时需要标记该节点是否已经在当前这条路径上,否则,我们求出的次短路是不正确的,排除
阅读全文
摘要:纯搜索题 一开始思路比较混乱,但是仔细想想便能得出正解。 我们预处理出每一棵子树的大小、每一层的儿子们,之后进行一次dfs,暴力枚举删除每一棵子树,同时更新答案,同时注意标记是否删除。搜索完成后回溯。最终就能得出答案。 1 #include <bits/stdc++.h> 2 using names
阅读全文
摘要:一道关于优先队列的搜索题。 我们建立一个小根堆,将开始确定的值放进去,然后进行bfs。 对于每个点,向上下左右四个方向扩展,并且更新答案,同时将没入队的节点入队即可。 最后,我们得到了一个搜索完成的图,我们判断一下合法性,输出答案即可。 这道题有一个坑点:输入可能重复同一节点但权值不同,这种情况应当
阅读全文
摘要:dfs+dp 我们要在一个大矩阵中选出一个小矩阵使得小矩阵的分值最小 所以我们先用dfs枚举选哪些行,再在dfs选的行的基础上对列进行dp,最后更新答案即可。 具体地,我们先通过dfs枚举r行,然后计算两个数组:sum[i][j]表示在当前dfs确定的行的状态下,第i列和第j列相邻时产生的分值。s[
阅读全文
摘要:记忆化搜索的经典例题 一个显然的想法,直接枚举每一个点作为起点然后dfs,求出最大值。显然这种做法一定会TLE,我们不妨进行一下优化:由于每一个点会被重复搜索,我们不妨进行记忆化,当这一个点搜索完成后,我们记下从这个点出发的最优解。下次搜索到这个点时我们就可以O(1)返回答案,这样搜索效率大大提高,
阅读全文
摘要:一道鬼畜的题目,洛谷给的标签是紫题,怎么可能是紫题…… 原本我想找出在起点到终点的路径上的割点,但是看到了这良心的数据之后…… 由于数据很小,所以我们枚举中间点,然后进行一遍dfs,判断不经过这个中间点这张图是否联通即可。 这就能过?? 是的……时间复杂度为O(n2) 1 #include <ios
阅读全文
摘要:一道非常棒的搜索题,做完之后感觉神清气爽…… 可以肯定的是,本题属于走地图一类的搜索题,适合用bfs求解,然而本题细节极多,有很多需要注意的地方。 我们定义状态三元组(x,y,z)表示当前移动到位置(x,y),且朝向z(我们不妨假定z=0意味着长方体立在地面上,z=1 意味着长方体横躺,x,y表示左
阅读全文
摘要:这道题是洛谷“八数码难题”的升级版,洛谷只要求出最少步数,而本题要输出结果。 我们在搜索的时候记录每一个状态的前驱,最后输出的时候递归即可。 我们采用A*算法进行搜索,设计估价函数为当前状态每个点与目标状态每个点的曼哈顿距离之和。在搜索时建立一个小根堆维护即可。 代码细节比较多,注意对细节的处理。可
阅读全文
摘要:本来想用双向广搜的,但是不太好保存路径,所以我就用的普通的bfs 思路很简单,从初始状态直接搜,每次扩展三个状态,用函数模拟一下三种变换,用map存储路径即可(拒绝康托展开,拒绝哈希,拒绝状压) 不得不说,对于数据不是很毒瘤的题,STL是真的好用啊…… 1 #include <iostream> 2
阅读全文
摘要:读完题,这是一道和bfs联通快有关的搜索题,肯定要搜索一些联通快,而这道题的难点在于如何判断当前的联通快属于山峰还是山谷。 因此,我们设计一个算法,在用bfs求联通快的同时,判断当前联通快是山峰山谷或者啥都不是。 具体地,我们像往常一样搜索联通快,若扩展的节点高度与当前联通快不同,则开始判断:如果大
阅读全文
摘要:最短路是一个妇孺皆知的算法,可以用多种方法解决。但是第k短路…… 以Dijkstra为例,对于s->t的第k短路,即t点在堆中第k次取出的结果。 于是我们想到了一个朴素的算法:用Dijkstra反复执行,直到t点在堆中第k次取出时结束。 考虑一下优化:用A*算法优化。 根据A*估价函数的设计原则,x
阅读全文
摘要:这是一道搜索题,我采用双向广搜+状压解决,对每一个状态枚举可以移动的位置,将状态扩展,然后通过对数组状压的方法进行记录结果。 另外,注意对答案为0的特判,因为起始状态与目标状态相同时无法搜出结果。 1 #include <iostream> 2 #include <cstdio> 3 #includ
阅读全文
摘要:这算是一道双向广搜或者是A*题,我用的是双向广搜,从初始状态和目标状态分别扩展状态,当他们第一次相遇时所用的步数即为答案。 1 #include <bits/stdc++.h> 2 using namespace std; 3 int ans=123804765; 4 int n; 5 const
阅读全文
摘要:一道难得的搜索好题,题目大意很简单,这里不再赘述,主要说一下思路 当然普通的bfs答案是正确的,但是在CH上评测会TLE一个点,所以我们采用效率更高的双向bfs 从初始状态和目标状态分别搜索,建立两个队列,分别扩展状态。如果一个队列扩展的状态已经被另一个队列搜索过了,那么便出现答案了。 另外,使用m
阅读全文
摘要:这是一道裸的广搜题吧…… 可能是《算法竞赛进阶指南》最水的一道题了…… 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 using namespace std; 6 queue<i
阅读全文
摘要:这是一道广搜题,难点在于对题目的理解和对细节的处理。 对于一个节点,可以向左上、左下、右上、右下四个位置扩展,根据地图的形态确定每一步扩展的代价。 将代价最小的节点放在队头,这样用双端队列来实现。每个节点最多进出队列一次,所以时间复杂度为O(r*c) 1 #include <iostream> 2
阅读全文