acm常用技巧一 二分 poj 1064 poj 2456

一.二分搜索

void Fun(){//lower_bound实现,不存在的情况下输出n
    int lb=-1,ub=n;
    while(ub-lb>1){//重复循环,直到解的范围<=1
        int mid=(lb+ub)/2;
        if(a[mid]>=k)
            ub=mid;//如果mid满足条件解的存在范围变成(lb,mid]
        else
            lb=mid;//如果不满足条件(mid,ub]
    }
    //lb+1=ub
    printf("%d\n",ub);
}
acm常用技巧一 二分 poj 1064 poj 2456_第1张图片

二.POJ 1064

给你n个木棍,你要把他们截成k个相同的小木棍,求小木棍的最大长度

#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <cstring>
#include <climits>
#include <cassert>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
using namespace std;
typedef long long LL;
const int MOD =1e9 + 7;
const int INF = 0x3f3f3f3f;

const int MXN=1e6;
int N,M;

void Rush()
{
    int T;
    scanf("%d",&T);
    for(int kas=1;kas<=T;++kas)
    {
        printf("Case %d: ",kas);
    }
}
int K;
double L[MXN];
bool C(double x){
    int num=0;
    for(int i=0;i<N;++i)
        num+=(int)(L[i]/x);
    return num>=K;
}
void Fun(){
    double lb=0,ub=1e10;
    for(int i=0;i<100;++i){
        double mid=(lb+ub)/2;
        if(C(mid)) lb=mid;
        else ub=mid;
    }
    printf("%.2lf\n",floor(ub*100)/100);
}
int main() 
{
    while(~scanf("%d%d",&N,&K)) 
    {
        for(int i=0;i<N;++i)
            scanf("%lf",&L[i]);
        Fun();
    }
    return 0;
}

三.POJ 2456

题意:在一位坐标上给N个点,将C头牛放在N个点中的C个点上使C头牛之间的最小距离最大

解法:C(d):=可以使最近的两头牛的距离不小于d,求满足C(d)的最大的d

int N,M;
int x[MXN];
bool C(int d){
    int last=0;
    for(int i=1;i<M;++i){
        int crt=last+1;
        while(crt<N&&x[crt]-x[last]<d){
            crt++;
        }
        if(crt==N) return 0;
        last=crt;
    }
    return 1;
}
void Fun(){
    sort(x,x+N);
    int lb=0,ub=INF;
    while(ub-lb>1){
        int mid=(lb+ub)/2;
        if(C(mid)) lb=mid;
        else ub=mid;
    }
    printf("%d\n",lb);
}

四.最大化平均值


int n,k;
int w[MXN],v[MXN];

double y[MXN];
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 Fun(){
    double lb=0,ub=INF;
    for(int i=0;i<100;++i){
        double mid=(lb+ub)/2;
        if(C(mid)) lb=mid;
        else ub=mid;
    }
    printf("%.2f\n",ub);
}
acm常用技巧一 二分 poj 1064 poj 2456_第2张图片

你可能感兴趣的:(ACM)