【二分】

Posted on 2018-05-12 21:11  som_nico  阅读(93)  评论(0编辑  收藏  举报

类似最大(小)值最大(小)化的问题都可以用二分来解决。

可以定义一个条件 C(x)  那么就是求满足某个条件 C(X)的最小的x

如果所有的x'>=x都满足C(x'),那么就可以用二分搜索来求最小的x

左端点初始化为不满足条件的值,右端点初始化为满足条件的值,每次取中点mid,判断C(mid)是否满足并且缩小范围,直到足够小了为止。

 

 

另外,STL里的lower_bound   upper_bound是求二分的函数

#include <algorithm>//必须包含的头文件
#include <stdio.h>
using namespace std;
int main()
{
    int n,a[100],m;
    int left,right,i;
    scanf("%d",&n);//设初始数组内元素有n个
    for(i=0;i<n;i++)
        scanf("%d",&a[i]);
    scanf("%d",&m);//插入的数为m
     left = upper_bound(a,a+n,m)-a;//按从小到大,m最多能插入数组a的哪个位置
     right = lower_bound(a,a+n,m)-a;//按从小到大,m最少能插入数组a的哪个位置
 
     printf("m最多能插入数组a的%d\n",left);
     for(i=0;i<left;i++)
        printf("%d ",a[i]);
    printf("%d ",m);
    for(i=left;i<n;i++)
        printf("%d ",a[i]);
 
    printf("\n");
 
    printf("m最少能插入数组a的%d\n",right);
    for(i=0;i<right;i++)
        printf("%d ",a[i]);
    printf("%d ",m);
    for(i=right;i<n;i++)
        printf("%d ",a[i]);
    return 0;
}

 

 

上例题!!

POJ 2456疯牛   这个是最大化最小值

【POJ】1064Cable master   这个是假定一个解并判断是否可行

最大化平均值问题:

有n个物品的重量个价值分别是wi和vi,从中选出k个物品是的单位重量的价值最大。

分析:

∑vi / ∑wi 这个式子是我们需要求的单位重量的价值。

∑vi / ∑wi >= x

∑(vi - x*wi) >= 0

判断这个式子是否成立即可。这下就可以用一个数组来保存vi - x * wi 的值,并进行排序,从大到小贪心地进行选择求和,如果求和的值大于0,那么此时 的x就是成立的。

const maxn = 2000;
const int inf = 0x3f3f3f3f;
int n, k;
int w[maxn], v[maxn];
double y[maxn];
bool C(double x){//计算是否满足条件
    for(int i=0;i<n;i++){
        y[i]=v[i]-x*w[i];
    }
    sort(y,y+n);
    double sum=0;
    for(int i=0;i<k;i++){
        sum+=y[n-i-1];
    }
    return sum>=0;
}
void solve(){
    double lb=0,ub=inf;
    for(itn i=0;i<100;io++){
        double min=(lb+ub)/2;
        if(C(mid)) lb=mid;
        else ub=mid;
    }
    printf("%.2f\n",ub);
}