剪枝搜索

剪枝搜索是搜索中常用的一个方法,Binary Search就是一个经典的剪枝搜索例子,在Biniary Search中

int binarySearch(int A[], int low, int high, int key)
{
    int mid;
    while (low <= high)
    {
        mid = (low + high) >> 1;
        if (key < A[mid]) high = mid - 1;
        else if (key > A[mid]) low = mid + 1;
        else return mid;
    }
    return -1;
}

我们可以明显看到,当目标被锁定在一半区域内时,就剪掉另一半,并对所在的一半进行搜索。而此时问题化简成为一个只有一半数据规模的子问题,递归这一过程,最终就可以在常数时间解决搜索问题。

另一个剪枝搜索的经典实例是寻找一组数中第K小的数的值,直观的想法是进行一次排序,而后求解。但即使是使用最合适于此问题的堆排序,也要用到O(NlogN)的时间,实际上,利用剪枝搜索有一种O(n)时间的算法如下:

选取数组中一个数P,遍历数组,将所有数据与P比较,小于P的数字置于集合S1,等于P的数字置于集合S2,大于P的数字置于集合S3

若S1.size>K,舍弃S2,S3,以S1为基础重复此问题。

否则 若S1.size+S2.size>K,则P为第K个数的值。

否则 舍弃S1,S2,以S3为基础重复此问题。

代码以后补

对于剪枝搜索问题的复杂度,我们可以看到

T(n)=T((1-f)*n)+O(n^k),最终的复杂度取决于k即为O(n^k),当n趋于无穷时,解决问题的实质复杂度和解决子问题的复杂度趋于一致。

(例如,对于Binary Search,T(n)=T(n/2)+C

设n=2^k,则有T(2^k)=T(2^(k-1))+C=(T(2^(k-2))+C)+C=T(1)+k*C

即T(n)=log(n)*C+T(1),所以binary search是一个O(log(n))的算法,在n趋于无穷时log(n)趋于常数代价)

时间: 2024-10-14 00:35:40

剪枝搜索的相关文章

朴素搜索dfs, 简单的剪枝搜索

为做一个项目选择最合适的语言固然重要,但是,掌握一门自己熟练的兵器,也很重要. ===================================================================================================================== 继续总结搜索类的题目,这一类的题目,目前仅分析简单粗暴的dfs搜索,以及简单的剪枝. 参考的题目: http://acm.hdu.edu.cn/showproblem.php?pid=

ZOJ 1136 Multiple(BFS + 数论 同余剪枝 搜索数字的倍数 )

ZOJ Problem Set - 1136 Multiple Time Limit: 10 Seconds Memory Limit: 32768 KB a program that, given a natural number N between 0 and 4999 (inclusively), and M distinct decimal digits X1,X2..XM (at least one), finds the smallest strictly positive mult

POJ 3134 Power Calculus (迭代剪枝搜索)

题目大意:略 题目里所有的运算都是幂运算,所以转化成指数的加减 由于搜索层数不会超过$2*log$层,所以用一个栈存储哪些数已经被组合出来了,不必暴力枚举哪些数已经被搜出来了 然后跑$iddfs$就行了 可以加一个剪枝,设你选择的最大迭代深度为K,现在如果当前组合出的数$x$,满足$x*2^{K-dep}<n$,说明$n$一定无法被$x$组合出来(即自己不断加自己),$x$对于答案是一定无意义的,就跳出 1 #include <queue> 2 #include <cstdio&g

数独--暴力、剪枝搜索

import java.util.Scanner; public class Main { static int arr[][]; static Scanner in = new Scanner(System.in); public static void main(String[] args) { arr = new int[9][9]; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { arr[i][j] = in.ne

搜索专题小结及例题:POJ2251&amp;POJ1426&amp;POJ3087&amp;POJ2488

图的遍历也称为搜索,就是从图中某个顶点出发,沿着一些边遍历图中所有的顶点,且每个顶点仅被访问一次,遍历可采取两种不同的方式:深度优先搜索(DFS)和广度优先搜索(BFS). 1.DFS算法思想` 从顶点v出发深度遍历图G的算法 ① 访问v0顶点,置vis[v0]=1,搜索v0未被访问的邻接点w,若存在邻接点w,则dfs(w),直到到达所有邻接点都被访问过的顶点u为止,接着退回一步,看是否还有其他没有被访问的邻接点.如果有,则访问此顶点,进行前述类似的访问,如果没有,就在退回一步进行搜索,重复上述

洛谷——P1034 矩形覆盖

https://www.luogu.org/problem/show?pid=1034 题目描述 在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示.例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一. 这些点可以用 k 个矩形(1<=k<=4)全部覆盖,矩形的边平行于坐标轴.当 k=2 时,可用如图二的两个矩形 sl,s2 覆盖,s1,s2 面积和为 4.问题是当 n 个点坐标和 k 给出后,怎样才能使得覆盖所

五子棋计算思路

五子棋分为有禁手和无禁手,有禁手就是在无禁手的规则的基础上加上禁手规则,具体是规则不讲了.所以就人机对战来讲,从无禁手来做,比较好做.这里只讲无禁手的情况.无禁手就是只要能连成5个子,或者5个子以上,就算赢.    而计算机博弈要解决的问题,抽象地讲只有一个问题“下一步怎么走”,对五子棋来讲,就是下一步在哪个点落子.一般的思路在 棋类人机对战的一般原理 - BillySir - 博客园  已经有说.下面重点讲五子棋特有的算法思路. 下一步怎么走,总体思路:    1.如果下一步能赢,就走这一步 

Qt版本中国象棋开发(四)

内容:走法产生 中国象棋基础搜索AI, 极大值,极小值剪枝搜索, 静态估值函数 理论基础: (一)人机博弈走法产生: 先遍历某一方的所有棋子,再遍历整个棋盘,得到每个棋子的所有走棋情况(效率不高,可以改进) 1 void SingleGame::getAllPossibleMove(QVector<Step *> &steps) 2 { 3 int min, max; 4 if(this->_bRedTurn) 5 { 6 min = 0, max = 16; 7 } 8 els

codeforce Pashmak and Buses(dfs枚举)

1 /* 2 题意:n个同学,k个车, 取旅游d天! 3 要求所有的学生没有两个或者两个以上的在同一辆车上共同带d天! 输出可行的方案! 4 5 对于d行n列的矩阵,第i行第j列表示的是第i天第j个同学所在的车号! 6 也就是保证所有行不全相同,即每一列都是不相同的! 7 如果每一列都不相同就是表示第j个同学(第j列)在这d天中不会和其他同学(列)在这d天中 都在同一辆车中! 8 9 思路:对于每一列我们枚举d天该学生所在的车号!它的下一列只保证有一个元素和它不同就行了!依次下去! 10 11