poj 几道简单的二分题

poj 3273 Monthly Expense

题意:
有n个数,划分成m块,和最大的一块最小是多少?
分析:
最大值最小问题,二分答案。

#include<cstdio>
using namespace std;
typedef long long ll;
const int N=1e5+9;
int a[N],n,m;
bool ok(int x)
{
    int k=m,t=0; //k是块数,t是某一块的和
    for(int i=0;i<n;i++){
        if(t+a[i]<=x){
            t+=a[i];
        }
        else{
            t=0;
            k--;
            i--;
        }
        if(k<0)return false;
    }
    return k>0;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)scanf("%d",&a[i]);
    int l=0,r=1e9;
    while(l<r){
        int m=l+(r-l)/2;
        if(ok(m))r=m;
        else l=m+1;
    }
    printf("%d\n",l);
    return 0;
}

poj 3258 River Hopscotch

题意:
一条河L宽,河中间有n个落脚点,问移走m个落脚点后,过河时,跨越的最短距离最大是多少?
分析:
读完这题,最小值最大问题,先想到二分答案,但是仔细想了想之后觉得不行,因为这是确定的移走m块石头,就拿样例来讲,如果二分答案是3,那么只能移走一块石头(2),不行,如果二分答案是5,那么要移走三块石头,也不行。左右都不行还怎么二分啊?于是写了个贪心,WA了。后来又仔细想了想,其实对于答案是3这种情况,我们可以认为这是可行的(虽然没移够m块,但是继续二分可以得到最优解)。所以这题二分就可以了。

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+9;
int a[N],n,m,L;
bool ok(int x)
{
    int pre=0;
    for(int i=1;i<=n-m;i++){ 
        int cur=pre+1;
        while(cur<=n&&a[cur]-a[pre]<x)cur++;
        if(cur==n+1)return false; //移走的数量超过了m块
        pre=cur;
    }
    return true;
}
int main()
{
    //freopen("f.txt","r",stdin);
    scanf("%d%d%d",&L,&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    sort(a+1,a+1+n);
    a[0]=0;
    a[++n]=L;
    int l=0,r=L;
    while(l<r){
        int m=l+(r-l+1)/2;
        if(ok(m))l=m;
        else r=m-1;
    }
    printf("%d\n",l);
    return 0;

poj 1905 Expanding Rods

题意:
固定的钢管热膨胀,会向上弯曲,求上升的高度?
分析:
求一下边角关系,然后二分答案即可。

#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
int main()
{
    double L,n,c;
    while(~scanf("%lf%lf%lf",&L,&n,&c)){
        if(L<0&&n<0&&c<0)break;
        double s=(1+n*c)*L;
        double l=0,r=0.5*L;
        while(r-l>1e-6){
            double m=(l+r)/2;
            r=(4*m*m+L*L)/8/m;
            if(2*r*asin(L/2/r)<s)l=m;
            else r=m;
        }
        printf("%.3f\n",l);
    }
    return 0;
}

poj 3122 Pie

题意:
有n个圆Pie,每个半径ri,有m+1个人,问每个人分相同面积的一片Pie,最大的面积可能是多少?
分析:
二分答案,然后判断即可。

#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
const double PI=acos(-1.0);
const int N=1e4+9;
double s[N];
int n,m,r;
bool ok(double x)
{
    int cnt=0;
    for(int i=0;i<n;i++){
        double t=s[i];
        while(t>x)t-=x,cnt++;
    }
    return cnt>=m+1;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++){
            scanf("%d",&r);
            s[i]=PI*r*r;
        }
        double l=0,r=PI*10000*10000;
        while(r-l>1e-6){
            double m=(l+r)/2;
            if(ok(m))l=m;
            else r=m;
        }
        printf("%.4f\n",l);
    }
    return 0;
}
posted @ 2016-08-03 17:41  HARD_UNDERSTAND  阅读(1043)  评论(0编辑  收藏  举报