二分搜索例题_dfs和bfs算法的区别「建议收藏」

二分搜索例题_dfs和bfs算法的区别「建议收藏」本篇讲的是常见的搜索模板,搜索其实非常好写,下面我将已典型的题目为例子介绍几种常见的搜索方式

  本篇讲的是常见的搜索模板,搜索题的解法时比较固定的,只要把模板记熟,加上自己找几道习题练习体会后,相信各位下次遇到这类题一定能拿下!!

下面我将已典型的题目为例子介绍几种常见的搜索方式。

 

1.二分搜索

二分搜索代码模板:

2fa1aa5647c84624a24cf887d8ab2340.png

例题:

5d2dc3b9432041f6a7b5cc32a88e3581.png

#include<bits/stdc++.h>
using namespace std;

double n;
const double eps = 1e-12;
//二分搜索
int main() {
	int t;
	cin>>t;
	while(t--) {
		cin>>n;
		double l = 0,r = 100000,res = -1;
		while(l<=r) {
			double mid = (l+r)/2;
			if(abs(mid*mid*mid - n) <= eps) {
				res = mid;
				break;
			}
			if(mid*mid*mid>n) r = mid - 0.0001;
			else if(mid*mid*mid<n) l = mid+0.0001,res = mid;
		}
		printf("%.3lf\n",res);
	}

	return 0;
}

二分搜索是只能对有序的数据处理的方式。并且每次操作可以将未搜索的区间减少一半,因此速度十分的快。

前面说了每次搜索将搜索的区间减少一半,因此二分搜索的关键主要是将数据区间的更新,在每次操作过程中需要跟(L+R)/ 2 得到的mid 中间值去比较,如果小于mid,则R = mid-1;大于mid,则L = mid + 1;当L不小于R时,循环结束,此时mid就是想要的值。

2.三分搜素

三分搜索和二分搜索类似,模板可以参考下面的例题。

例题:

162b7ae14b6a4867bad1e56d0cf9a65b.png

#include<bits/stdc++.h>
using namespace std;
//三分法
#define double long double
int a,b,c,Q;
const double esp = 1e-9;
double check(double x){
	return a * x * x + b * x + c;
}


int main(){
	cin>>a>>b>>c>>Q;
	while(Q--){
		double l,r;
		cin>>l>>r;
		while(r - l > esp){
			double lmid = l + (r - l) / 3;
			double rmid = r - (r - l) / 3;
			if(check(lmid)>check(rmid)) r = rmid;
			else if(check(lmid)<check(rmid)) l = lmid;
			else l = lmid,r = rmid;
		}
		cout << setprecision(2) << fixed << a * l * l + b * l + c << '\n' ;
	}
	return 0;
}

 二分搜索也是有局限,它只能对有序的数据进行搜索,也就是数据必须单调。本题给出的二元一次函数,明显非单调。这就要用到三分搜索了,就是将原来的搜索区间分成三份,如下图。分别计算LMID和RMID,然后对其进行比较,若LMID大于RMID,那最大值一定在L到RMID这区间内。小于类似。

 3871b2573f9d4867a14eb2bdbfac7863.png

 3.BFS

BFS的代码模板:

575decd43ae8405089652f7c5492b6b8.png

例题:

bcd3e0071a134901969d50b990166b5c.png

#include<bits/stdc++.h>
using namespace std;


int x,y,x2,y2;
int mp[105][105];
int n,m;
bool vis[105][105];  //标记地图上的点是否访问过
int dir[4][2] = {
  
  {1,0},{-1,0},{0,1},{0,-1}}; //搜索方向
struct node{
	int a,b,c;
};  //方便计算和存入队列中

bool check(int x,int y){ //排除边界点、地图不能访问的点、以及已经访问过了的点
	if(x<1 || x> n || y<1 || y>m || !mp[x][y] || vis[x][y]) return false;
	return true;
}
int bfs(int x,int y){
	queue<node> q;
	q.push(node{x,y,0});
	vis[x][y] = 1;
	while(!q.empty()){
		node u = q.front();
		q.pop();
		if(u.a == x2 && u.b == y2) return u.c;
		for(int i = 0;i<4;i++){
			int xx = dir[i][0]+u.a;
			int yy = dir[i][1]+u.b;
			if(!check(xx,yy)) continue;
			vis[xx][yy] = 1;
			q.push(node{xx,yy,u.c+1});
		}
	}
	return -1;
}
int main()
{
	cin>>n>>m;
	for(int i = 1;i<=n;i++){
		for(int j = 1;j<=m;j++){
			cin>>mp[i][j];
		}
	}
	cin>>x>>y>>x2>>y2;
	cout<<bfs(x,y)<<endl;
	return 0;
}

BFS适用于求最短路径,该算法的搜索过程:

  • 将起始位置加入队列
  • 从队列开头取出一个元素,将这个元素四周可到达并且未被访问的点加入队列

因为队列先进先出的特性,只有当所有距离为 111的点被取出队列后,才会遍历距离为 222 的点,而距离为 111的点能到达的只有距离为 222的点,这也就保证这搜索答案的正确性。

 4.DFS+剪枝

DFS的代码模板:

a1b6db17fe9d43bcab003462747c4642.png

例题:

dc2db43c2dc74f6ba5574ba5dcc92d92.png

#include <bits/stdc++.h>
using namespace std;
int vis[17];
int m[5][5];
int cnt = 0;

bool judge() {  
    for (int i = 0; i < 4; i ++ ) { //四行四列的和
        if (m[i][0] + m[i][1] + m[i][2] + m[i][3] != 34) return 0;
        if (m[0][i] + m[1][i] + m[2][i] + m[3][i] != 34) return 0;
    }
    if (m[0][0] + m[1][1] + m[2][2] + m[3][3] != 34) return 0;//对角线
    if (m[0][3] + m[1][2] + m[2][1] + m[3][0] != 34) return 0;
    return 1;
}

void dfs(int n) {
    if (n == 16) {
        if (judge())    cnt ++;
        return;
    }
    if (n%4 == 0)  //简单剪枝:检查第一行的和是不是34
      if (m[n/4 - 1][0] + m[n/4 - 1][1] + m[n/4 - 1][2] + m[n/4 - 1][3] != 34)
         return;

    for (int i = 2; i <= 16; i ++ ) {
        if (vis[i] == 0) {
            m[n/4][n%4] = i;
            vis[i] = 1;
            dfs(n + 1);
            vis[i] = 0;
        }
    }
}

int main() {
     m[0][0] = 1;
     dfs(1);
     cout << cnt << endl;   //416
    return 0;
}

本质上是暴力把所有的路径都搜索出来,它运用了回溯,保存这次的位置并深入搜索,都搜索完便回溯回来,搜下一个位置,直到把所有最深位置都搜一遍(找到目的解返回或者全部遍历完返回一个事先定好的值)。要注意的一点是,搜索的时候有记录走过的位置,标记完后要改回来。 

这题的递归出口是所有数都填完,然判断该解是不是题目要求的解,是的话cnt++。有一个剪枝,可以降低时间复杂度,即当一行的和加起来不是34时,就一定不是我们要的解,往后就没必要再搜索下去了。

 

 

今天的文章二分搜索例题_dfs和bfs算法的区别「建议收藏」分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/63533.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注