20201-1-22 二分查找

  1. 二分查找的作用是将O(n)的复杂度变成O(logn)
  2. mid = l+r >> 1 整数右移一位即相当于除以二
    若为浮点数则写作(1+r)/2
  3. pi的定义:#define pi acos(-1.0)
  4. const double eps = 1e-6
    while( l+eps<r ) eps指无限逼近

二分题目A:在1到100中寻找能满足制定式子的数,保留四位小数

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iomanip>
#include<cmath>//幂函数pow()头文件
const double eps=1e-6;
using namespace std;

int T;
double n;
double ans1;

bool check1(double x)
{
    
    
	if(8*pow(x,4)+7*pow(x,3)+2*pow(x,2)+3*x+6.0>=n)
	return 1;
	else
	return 0;
}
int main()
{
    
    
	cin>>T;
	
	while(T--)
	{
    
    
		cin>>n;//输入实数
			if(n<6||n>8*pow(100,4)+7*pow(100,3)+2*pow(100,2)+3*100+6.0)
			cout<<"No solution!"<<"\n";
			else
			{
    
    
			double l=0.0,r=100.0; 
			while(l+eps<r)//l无限逼近于r
			{
    
    
				double mid=(l+r)/2;
				if(check1(mid))
				{
    
    
					r=mid;
					ans1=mid;
				}
				else 
				l=mid;
			}
			cout<<fixed<<setprecision(4)<<ans1<<"\n";//保留四位小数(fixed)的意思是若无零则自动补零
			}
	}

	return 0;
}

二分题目B:在数列中找到能够符合两项相加等于规定数字的个数

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
const int maxn=1e6+9;
using namespace std;

int T,n,k;
int a[maxn];
int ans1;

bool check(int x)
{
    
    
	int l=1,r=n;
	while(l<r)
	{
    
    
		int mid=l+r>>1;
		if(a[mid]==x) return 1;
		else if(a[mid]>x)
		r=mid;
		else
		l=mid+1;
	}
	return 0;
}
int main()
{
    
    

	cin>>T;
	while(T--)
	{
    
    
		memset(a,0,sizeof a);
		ans1=0;
		cin>>n>>k;
		for(int i=0;i<n;i++)
			cin>>a[i];
		sort(a,a+n+1);
		for(int i=1;i<=n;i++){
    
    
			if(check(k-a[i]))
			{
    
    
				ans1++;
				if(a[i]==a[i-1]&&i!=1)
				ans1--;
			}
		}
			cout<<ans1<<"\n";
	}

	return 0;
}

二分题目C:将牛放入马厩中,求最小值中的最大值

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iomanip>
#include<cmath>
#define pi acos(-1.0)
const int maxn=1e6+9;
const double eps=1e-6;
using namespace std;

int n,c;
int a[maxn];

bool check(int x)
{
    
    
	int num=1,j=0;
	for(int i=1;i<n;i++)
	{
    
    
		if(a[i]-a[j]>=x)
		{
    
    
			num++;
			j=i;
		}
	}
	if(num>=c)
		return 1;
		else
		return 0;
}
int main()
{
    
    
	int mid;
	scanf("%d%d",&n,&c);
	for(int i=0;i<n;i++)
		scanf("%d",&a[i]);
    sort(a,a+n);
    int l=1,r=a[n-1]-a[0];//在最大值和最小值之间找一个最小值的最大值
    while(l<r)
    {
    
    
    	mid=l+r>>1;
    	int num=1,j=0;

	if(check(mid))
		l=mid+1;
   	else
   	r=mid;
	}
	cout<<r-1<<"\n";
	return 0;
}

二分查找D:分蛋糕

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iomanip>
#define pi acos(-1.0)
const int maxn=1e6+9;
using namespace std;

const double eps=1e-6;
double a[maxn];
int n,f,T;
double ans1;

bool check(double x)
{
    
    
	int n1=0;
	for(int i=0;i<n;i++)
	{
    
    
		n1+=(int)((a[i]*a[i]*pi)/x);
	}
	if(n1>=f+1)
	return 1;
	else
	return 0;
}
int main()
{
    
    
	cin>>T;
	while(T--)
	{
    
    
		cin>>n>>f;
		for(int i=0;i<n;i++)
		{
    
    
			cin>>a[i];
		}
		sort(a,a+n);
		double l=0,r=a[n-1]*a[n-1]*pi;//在最大体积和最小体积间找可能满足情况的体积
		double ans1=0;
		while(l+eps<r)//无限逼近
		{
    
    
			double mid=(l+r)/2;
			if(check(mid))
			{
    
    
				l=mid;
				ans1=mid;
			}
			else
			r=mid;
		}
		cout<<fixed<<setprecision(4)<<ans1<<"\n";
	}

	return 0;
}

二分查找E:牛跳石头,在n块石头中取m块,再求最小值的最大值

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iomanip>
#include<cmath>
//#define pi acos(-1.0)
const int maxn=1e6+9;
const double eps=1e-6;
using namespace std;

int l,m,n,L;
int a[maxn];
int main()
{
    
    
	cin>>L>>n>>m;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	a[0]=0;
	a[n+1]=L;
	sort(a,a+n+2);
	int l=0,r=a[n+1];
	while(l<=r)
	{
    
    
		int mid=l+r>>1;
		int j=0,num=0;
		for(int i=1;i<=n+1;i++)
		{
    
    
			if(a[i]-a[j]<=mid)//如果两个石头之间的距离小于mid则跳过
				num++;
			else
				j=i;
		}
		if(num>m)
			r=mid-1;
		else
			l=mid+1;
	}
	cout<<l<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/abc123580/article/details/113002648