搜索有关的好题和思路
枚举#
等差数列(ZJOI2004)###
给定 n(1<=n<=100)个数,从中找出尽可能多的数使得他们能够组成一个等差
数列.求最长的等差数列的长度.
我们首先必须对这个数列进行排序,排序我们采用 QuickSort。然后我们
就能够很快想到一系列的方法:枚举头部、第二个与尾部。
但是我们为什么要枚举三个呢?头部当然不用说,第二个是为了与第一个作
差,得出公差。然后就可以递推地去枚举到最后。
这样我们就能够得出一个O(n3)的方法,而在n<=100 的时候保证不会超
时。
广告印刷(TOJ 一周年比赛)###
最近,afy 决定给 TOJ 印刷广告,广告牌是刷在城市的建筑物上的,城市里
有紧靠着的 N 个建筑。afy 决定在上面找一块尽可能大的矩形放置广告牌。我们
假设每个建筑物都有一个高度,从左到右给出每个建筑物的高度 H1,H2…HN,且
0 < Hi<=1,000,000,000,并且我们假设每个建筑物的宽度均为 1。N <= 1,000,000,
要求输出广告牌的最大面积。
方法不难想到:如果要使涂刷的总面积是最大的,那么就必然有那么一个建
筑物被刷满。那么哪一个建筑物能够被刷满才能够使总体涂刷的面积是最大的
呢?沿袭上面的思路,我们穷举每一个建筑物,设它能够被刷满。于是我们可以
用两个循环来枚举它的左方与右方各自能够延伸到哪里(也就是求出覆盖到哪
里),然后这时的面积就可以用这个建筑物的高度*被覆盖建筑物的总个数,求
每次求出来的面积中的最大值。
此题的路径压缩可以采取类似并查集的方法,实现起来也很简单。由于具体
的实现与搜索关系不大,所以这里也就一笔带过了。
//维护两个并查集数组,一个向左一个向右能扩展的最远,m[i-1]>m[i],fa[i]=find(i-1),else fa[i]=i;
我认为此题与清北学堂2017的题相像,原题可使用暴力枚举,此题必用并查集优化,思想很好。
treasure
仓库扩张(USACO Contest DEC05)###
在 FJ 的农场里有 N(1<=N<=25000)个长方形仓库,这些仓库的四条边都分
别与 x 轴、y 轴平行,且四角坐标均为正数,范围为 0..1000000。这些仓库都不
互相重叠,但是可能有一些点或者一段边是它们共有的。
一次,FJ 得到了更多的奶牛去挤奶,因此他想扩张自己的仓库。一个仓库有
能够扩张的条件是它不与别的仓库存在任何一个公共角或者任意一段公共边。请
你计算有多少个仓库可以扩张。
这道题目枚举的方法有些特殊,需要一些枚举技巧。
首先在读入时,我们的处理方法是“拆边”,按横、纵两种拆。拆开以后,
我们应该把所有的横边排序,所有的纵边也排序。
横边排序规则: 1.按行排序。 2.行相等时按这一行的头坐标(线段左边端点
纵坐标)排序。 3.如果再相等就按线段右边端点纵坐标排序。这样就能够保证边
的有序性,为下面做好铺垫。竖边类同。
然后就是把所有的横边、纵边进行重叠处理。我们可以把它们分开处理。如
果重叠(或临接),则两个仓库都不能扩张。经过上述处理,我们可以发现我们
需要比较的边数已经大大减少。因此我们可以加上一些细节处理来加快速度。
行星队列(USACO Contest DEC05)###
平面上给出 N(1<=N<=770)个点(坐标均为 1..15000 之间的整数),要求
求出有多少组三个点在一条直线上。
这道题拿到后,首先我们会用枚举的方法,写出一个O(N3)的程序。这可能
可以过,但固然不是很好,在这里讲一下O(N2log2N)的方法。
首先当然是读入操作。读入完毕后,我们这里用斜率来优化。所谓斜率,即
为直线的倾斜角 α 的正切值。因为两点确定一条直线,故我们可以求出每两个
点的直线的斜率。我们先用预处理,把斜率求出保存。当然,如求斜率时遇到除
数为 0,则需另外处理(那就是与坐标轴平行的情况)。
然后把每一个点出发到所有点的直线按斜率排序。排序完毕,我们只需要开
i、 j二重循环去找这第三个点。因为两点确定一条直线,且每一点出发的直线都
已经按斜率排序,故我们只需要用O(log2N)的时间进行每一次查找。综合时间
复杂度为O((N2)*(log2N))=O(N2log2N)。
二分答案的应用