寒假之搜索(不是dfs/bfs)

2024-04-23 21:08
文章标签 不是 搜索 bfs dfs 寒假

本文主要是介绍寒假之搜索(不是dfs/bfs),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

线性搜索 二分搜索 借助STL标准库 进行搜索

1.线性搜索听名字就是以线的方式来遍历,直接从头到尾开始遍历,找到就找到,找不到就找不到。复杂度是O(n)。主要有两种方式来实现。

a:

bool linesearch(int *a,int num,int n)
{int i=0;a[n]=num;while(a[i]!=num)i++;if(i==n)return false;   //没有找到 return true;   		//找到了 
}

b:

bool linesearch(int *a,int num,int n)
{int i=0;for(i=0;i<=n;i++){if(a[i]==num){return false;}} return false;
}

2.二分搜索,复杂度为O( log(n) ),在一些数据量大的时候,可以用二分搜索。

bool binary(int laft,int right,int num)
{paixu();  //需要先排序,可以用一下 sort while(left<right){int mid=(left+right)/2;if(a[mid]==num)return true;else if(a[mid]>num)right=mid;else if(a[mid]<num)left=mid+1;}return false;
}

 二分搜索在一些题目上,有很多的变形,例如二分答案(二分加贪心的升级问题),对于区间的把握程度有很大的要求,需要多练习相关的题目,我下面讲讲具体的怎么处理问题的。

1.在大数据的情况下查找满足条件的数(前提是数据都是有序的),将区间一分为二,先判断中间值与查找数之间的大小关系,在左边那就继续在左边查找,在右边就相反操作。在不断的查找过程中,left 和 right  都是在不断的更新,当left 和 right 相等或者 left 大于 right 时,这时就不能再一分为二了。如果还没有查找到,就是真的没有;在二分的过程中,如果找到,就直接 return  掉。 这个left 和 right 如何变 根据题目的要求。

2.二分答案题型,属于难度提高题目,常常与贪心一起出现,不是仅仅二分数据,而是不断二分满足的答案,直到找到满足最优解的答案。(比如两者之间尽可能小的(间距)最大值或者最小值),这就要先满足 1 条件(尽可能小),然后再满足的二个条件是最大值和最小值 。这个就是二分答案,在不断的二分答案,找到最优的解。通常二分与很多算法都在一起使用,比如贪心等算法。就在二分过程当中判断此时答案是否符合标准,再进一步优化找到最优解。

POJ 2456 3273 2976 3122 1505 2018 HDU 5248 4004  2899 1969 4334 6383  洛谷1182 1824 noip 2012  CF 923B  

部分二分答案习题,自己可以练习。

 

看道例题:

 

给你一个n个整数序列和一个不同的q个整数序列t。写一个程序,输出c,t中的整数个数,也在集合s中。 

输入              

在第一行给出n。在第二行中,给出n个整数。第三行中给出了q。然后,在第四行中,给出q整数。

输出              

在一行中输出c。

约束条件              

s中的元素按升序排序

  • n ≤ 100000
  • q ≤ 50000
  • 0 ≤ an element in S ≤ 109
  • 0 ≤ an element in T ≤ 109
  • Sample Input 1
  • 5
    1 2 3 4 5
    3
    3 4 1

    Sample Output 1

    3

    Sample Input 2

    3
    1 2 3
    1
    5

    Sample Output 2

    0

    Sample Input 3

    5
    1 1 2 2 3
    2
    1 2

    Sample Output 3

    2

二分算法:

#include<stdio.h>
#include<iostream>
using namespace std;
#include<string>
#include<string.h>
#include<algorithm>
#include<queue>
#include<vector>
#include<list>
#include<set>
const int maxn=100005;
typedef long long ll;
bool erfen(ll *a,ll left,ll right,ll num)
{while(left<right){ll mid=(left+right)/2;if(num==a[mid])return true;else if(num<a[mid])right=mid;else if(num>a[mid])left=mid+1;}return false;
}
int main()
{ll num;ll a[maxn];ll i;ll n;ll k=0;cin>>n;for(i=0;i<n;i++)cin>>a[i];sort(a,a+n);ll q;cin>>q;for(i=0;i<q;i++){cin>>num;if(erfen(a,0,n,num))k++;}cout<<k<<endl;return 0;
}

用到STL 问题就相对于简单一点(其实一样)

下面看一个用一个 lower_bound 来实现:

代码:

#include<stdio.h>
#include<iostream>
using namespace std;
#include<string>
#include<string.h>
#include<algorithm>
#include<queue>
#include<vector>
#include<list>
#include<set>
const int maxn=100005;
typedef long long ll;
int main()
{ll k=0;ll i;ll a[maxn];ll n,q;cin>>n;for(i=0;i<n;i++)cin>>a[i];cin>>q;for(i=0;i<q;i++){ll num;cin>>num;ll pos=lower_bound(a,a+n,num)-a;if(a[pos]==num)k++;}cout<<k<<endl;return 0;
}

 下面就用一个 set 就可以实现,代码:

#include<stdio.h>
#include<iostream>
using namespace std;
#include<string>
#include<string.h>
#include<algorithm>
#include<queue>
#include<vector>
#include<list>
#include<set>
const int maxn=2000005;
typedef long long ll;
int main()
{ll k=0;ll num;int i;set<ll>s1;set<ll>s2;set<ll>::iterator it=s2.begin();int n,q;cin>>n;for(i=0;i<n;i++){cin>>num;s1.insert(num);}cin>>q;for(i=0;i<q;i++){cin>>num;s2.insert(num);}for(it=s2.begin();it!=s2.end();it++){if(s1.find(*it)!=s1.end())k++;}cout<<k<<endl;return 0;
}

简单说的说一下原理吧,先将 是数组排序(必要条件)否则二分不能实现,就是每次将区间分一半,在左边的话,就抛弃右边;在右边,就抛弃左边。大大的减少了时间。、

3.有的搜索就可以直接用STL实现,(比如一些set vector 有一些搜索的函数 find()  ),就可以直接套用。

看看题:

您的任务是编写一个简单字典程序,该程序实现以下指令:              

您的任务是编写一个简单字典程序,该程序实现以下指令:              

insert str:在字典中插入字符串str              

查找str:如果distinary包含str,则打印“yes”,否则打印“no”              

输入              

在第一行n中,给出了指令数。在以下n行中,n条指令以上述格式给出。              

产量              

对一行中的每个查找指令打印“是”或“否”。              

约束条件              

字符串由“a”、“c”、“g”或“t”组成              

1≤字符串长度≤12              

n=1000000 

代码:

#include<stdio.h>
#include<iostream>
using namespace std;
#include<string>
#include<string.h>
#include<algorithm>
#include<queue>
#include<vector>
#include<list>
#include<set>
const int maxn=100005;
typedef long long ll;
int main()
{char zifu[20];char zhiling[20];ll t;cin>>t;set<string>s;while(t--){cin>>zhiling>>zifu;if(zhiling[0]=='i'){s.insert(zifu);}else if(zhiling[0]=='f'){if(s.find(zifu)!=s.end())cout<<"yes"<<endl;else cout<<"no"<<endl;	}	}return 0;
}

这些 stl 的用法,应该要掌握,不了解的,可以看看博客学习一下。

 

 

 

 

 

这篇关于寒假之搜索(不是dfs/bfs)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/929891

相关文章

hdu1254(嵌套bfs,两次bfs)

/*第一次做这种题感觉很有压力,思路还是有点混乱,总是wa,改了好多次才ac的思路:把箱子的移动当做第一层bfs,队列节点要用到当前箱子坐标(x,y),走的次数step,当前人的weizhi(man_x,man_y),要判断人能否将箱子推到某点时要嵌套第二层bfs(人的移动);代码如下:

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

hdu1240、hdu1253(三维搜索题)

1、从后往前输入,(x,y,z); 2、从下往上输入,(y , z, x); 3、从左往右输入,(z,x,y); hdu1240代码如下: #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#inc

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d

poj 3050 dfs + set的妙用

题意: 给一个5x5的矩阵,求由多少个由连续6个元素组成的不一样的字符的个数。 解析: dfs + set去重搞定。 代码: #include <iostream>#include <cstdio>#include <set>#include <cstdlib>#include <algorithm>#include <cstring>#include <cm

hdu 4517 floyd+记忆化搜索

题意: 有n(100)个景点,m(1000)条路,时间限制为t(300),起点s,终点e。 访问每个景点需要时间cost_i,每个景点的访问价值为value_i。 点与点之间行走需要花费的时间为g[ i ] [ j ] 。注意点间可能有多条边。 走到一个点时可以选择访问或者不访问,并且当前点的访问价值应该严格大于前一个访问的点。 现在求,从起点出发,到达终点,在时间限制内,能得到的最大

poj 2195 bfs+有流量限制的最小费用流

题意: 给一张n * m(100 * 100)的图,图中” . " 代表空地, “ M ” 代表人, “ H ” 代表家。 现在,要你安排每个人从他所在的地方移动到家里,每移动一格的消耗是1,求最小的消耗。 人可以移动到家的那一格但是不进去。 解析: 先用bfs搞出每个M与每个H的距离。 然后就是网络流的建图过程了,先抽象出源点s和汇点t。 令源点与每个人相连,容量为1,费用为

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

hdu4277搜索

给你n个有长度的线段,问如果用上所有的线段来拼1个三角形,最多能拼出多少种不同的? import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;

POJ 3057 最大二分匹配+bfs + 二分

SampleInput35 5XXDXXX...XD...XX...DXXXXX5 12XXXXXXXXXXXXX..........DX.XXXXXXXXXXX..........XXXXXXXXXXXXX5 5XDXXXX.X.DXX.XXD.X.XXXXDXSampleOutput321impossible