浮点数、整数二分法

浮点数、整数二分法


一、概念

1.二分适用范围:

一个整体可以被分成两部分,此时所有事物必须属于这两部分中的一方,且没有事物可以同时属于双方,即满足【互补】【互斥】的特点。

2.二分关键:

找到中间值(分割这个整体的判断条件)。


 二、实例

下面来看看这两道算法题:

题目1——剪绳子【浮点数二分

 来源:AcWing 680. 剪绳子

思路:

分析题目,已知的是绳子的最终数量,求最大长度,这种情况很难求出来,但若是已知绳子长度反推绳子数量就很好求了,通过求出来的绳子数量与题目要求的进行对比,就可以推断出我们假设的长度是否符合题意了。

中间值:长度mid,如果通过mid求出来的绳子数量小于题目要求,则最终答案小于mid,否则将大于等于mid。

其余问题

1.缩短到什么范围可以得到答案?

一般求到题目要求的精度再加两个精度即可,或通过时间复杂度来计算,竞赛时c++最大时间复杂度在1e7~1e9范围内,以1e7为最佳求得最多可以循环多少次不会超时。

AC的代码:

#include<iostream>
using namespace std;

const int N=100010;
int g[N];

int n,m;//绳子个数,需求绳子个数

bool check(double d){
    int res=0;
    for(int i=0;i<n;++i){
        int temp=g[i]/d;
        res+=temp;
    }
    return res>=m;
}

int main(){
    cin>>n>>m;
    for(int i=0;i<n;++i)
        cin>>g[i];
    double min1=0,max1=1e9;
    while(max1-min1>1e-4)//因为要求精度是小数点后k位,按照经验来说求到1e-(k+2)即可 用for循环也行,循环100次
    {
        double mid=(min1+max1)/2;
        if(check(mid)) min1=mid;
        else max1=mid;
    }
    printf("%.2lf\n",max1);
    return 0;

}

题目2——分巧克力【整数二分

来源:AcWing 1227. 分巧克力

思路

大致思路和上一题一样,唯一需要注意的是当中间值不为整数时,应该将mid归为哪个区间。

这里有两个模板建议背熟:

模板1:我们将区间 [ l, r ] 分为 [ l, mid] 和 [mid + 1 , r], 此时求 mid 时不用 +1

int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = l + r >> 1;//等价于mid = ( l + r ) / 2;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    return l;
}

模板2:我们将区间 [l, r] 分为 [l, mid-1] 和 [mid, r], 此时为了防止死循环,所以求 mid 时需要 + 1 

int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}

什么时候用模板1,什么时候用模板2?

这个是不固定的,需要具体题目具体分析。但有个大大说当我们在找最小值边界的时候一定得用模板1,在找最大值边界时一定得用模板2,,这个先记住吧。

AC的代码:

#include<iostream>

using namespace std;
typedef long long LL;

const int N=100010;
int n,m;
int h[N],w[N];

bool check(int mid){
    LL res=0;
    for(int i=0;i<n;++i){
        res+=(LL)h[i]/mid*(w[i]/mid);
        if(res>=m) return true;
    }
    return false;
}
int main(){
    cin>>n>>m;
    for(int i=0;i<n;++i) scanf("%d%d",&h[i],&w[i]);

    int l=1,r=1e5;//保证了每个小朋友至少有一块蛋糕,所以最小值为1
    while(l<r){
        int mid=l + r + 1 >> 1;//上取整
        if(check(mid)) l=mid;
        else r=mid-1;
    }

    printf("%d\n",r);
    return 0;
}

好啦,感觉好绕~多刷点这种题大概就会了叭。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值