ACM 暑期培训——二分/三分专题

A - Light Bulb

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3203


#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#define INF 0x7fffffff
using namespace std;
double H,h,D;
double f(double x)
{
    return D*(h-x)/(H-x)+x;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lf%lf%lf",&H,&h,&D);
        double dl,dr,l=0,r=h,lmid,rmid;
        while(r-l>1e-8)
        {
            lmid=l+(r-l)/3.0;
            rmid=r-(r-l)/3.0;
            dl=f(lmid);
            dr=f(rmid);
            if(dl<dr) l=lmid;
            else r=rmid;
        }
        printf("%.3lf\n",dl);
    }
    return 0;
}
B - Turn the corner (HDU2438)

判断汽车能否过弯,这题做了好半天,简直就是数学题啊!(画图好麻烦,还这么丑!)


#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#define cot(a) (cos(a)/sin(a))
#define INF 0x7fffffff
using namespace std;
double x,y,L,d;
const double PI=acos(-1.0);
double f(double a)
{

    double S=y+x*cot(a);
    return (S*sin(a)-d)/(sin(a)*cos(a));
}

int main()
{
    while(scanf("%lf%lf%lf%lf",&x,&y,&L,&d)!=EOF)
    {
        double dl,dr,l=0,r=PI/2,lmid,rmid;
        for(int i=0;i<100;i++)
        {
            lmid=l+(r-l)/3.0;
            rmid=r-(r-l)/3.0;
            dl=f(lmid);
            dr=f(rmid);
            if(dl>dr)
                l=lmid;
            else r=rmid;
        }
        if(dl>L) cout<<"yes"<<endl;
        else cout<<"no"<<endl;
    }
    return 0;
}

C - The Moving Points  (HDU   4717)

给n个点,每个点有个速度,求所有点的最大距离最小的时刻。

一开始读错题了! 以为求最小距离最小的时刻。 ==! Wrong了8次!!!

还是三分,每次判断所有点的最远距离。

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#define INF 0x7fffffff
using namespace std;
int n;
struct point
{
    double x,y,vx,vy;
}p[400];

double dis(double t,int a,int b)
{
    double ax=p[a].x+t*p[a].vx;
    double bx=p[b].x+t*p[b].vx;
    double ay=p[a].y+t*p[a].vy;
    double by=p[b].y+t*p[b].vy;
    return (ax-bx)*(ax-bx)+(ay-by)*(ay-by);
}

double check(double x)
{
    double ans=0;
    int i,j;
    for(i=0;i<n;i++)
        for(j=i+1;j<n;j++)
            ans=max(dis(x,i,j),ans);
    return ans;
}

int main()
{
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&p[i].vx,&p[i].vy);

        double l=0,r=1e8,lmid,rmid,d=0;
        while(r-l>1e-8)
        {
            lmid=l+(r-l)/3.0;
            rmid=r-(r-l)/3.0;
            d=check(lmid);
            if(d>check(rmid))
                l=lmid;
            else r=rmid;
        }
        printf("Case #%d: %.2lf %.2lf\n",cas++,r,sqrt(d));
    }

    return 0;
}

D - Solve this equation  HDU   2199 

给你个函数,求零点,裸的二分。

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#define INF 0x7fffffff
using namespace std;
double Y;
double f(double x)
{
    return 8.0*x*x*x*x + 7.0*x*x*x + 2.0*x*x + 3.0*x + 6 - Y ;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lf",&Y);
        if(f(0)*f(100)>0)
        {
            printf("No solution!\n");
            continue;
        }
        double l=0,r=100,mid;
        for(int i=0; i<100; i++)
        {
            mid=(l+r)/2;
            if(f(mid)<0) l=mid;
            else r=mid;
        }
        printf("%.4lf\n",l);
    }
    return 0;
}

E - UmBasketella    POJ    3737

给你圆锥的表面积,求最大体积。

也是三分,用 g++交Wrong了三次,换c++就A了

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#define INF 0x7fffffff
using namespace std;
double S,L,h;
const double PI=acos(-1.0);
long double f(long double r)
{
    L=S-(PI*r*r);
    L/=PI*r;
    h=sqrt(L*L-r*r);
    return PI*r*r*h/3;
}

int main()
{
    while(scanf("%lf",&S)!=EOF)
    {
        double dl,dr,l=0,r=S,lmid,rmid;
        for(int i=0;i<100;i++)
        {
            lmid=l+(r-l)/3.0;
            rmid=r-(r-l)/3.0;
            dl=f(lmid);
            dr=f(rmid);
            if(dl<dr)
                l=lmid;
            else r=rmid;
        }
        printf("%.2lf\n%.2lf\n%.2lf\n",dl,h,l);
    }
    return 0;
}

F - Party All the Time   HDU   4355

刚开始看了半天没看懂什么意思。

就是说有n个小精灵,他们走过一段距离就有个不开心指数,问聚集所有小精灵所达到的最小不开心指数之和是多少。

还是极值问题,要求四舍五入化成整数。直接%.0lf好像就行了。

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#define INF 0x7fffffff
using namespace std;
double x[100005];
double w[100005];
int n;
double f(double p)
{
    double sum=0;
    for(int i=0;i<n;i++)
    {
        double s=fabs(p-x[i]);
        sum+=s*s*s*w[i];
    }
    return sum;
}
int main()
{
    int T,i,C=0;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        double Max=0;
        for(i=0;i<n;i++)
        {
            scanf("%lf%lf",&x[i],&w[i]);
            Max=max(Max,x[i]);
        }
        double l=0,r=Max,m1,m2;
        while(r-l>1e-4)
        {
            m1=l+(r-l)/3;
            m2=r-(r-l)/3;
            if(f(m1)>f(m2)) l=m1;
            else r=m2;
        }
        printf("Case #%d: %.0lf\n",++C,f(m1));
    }

    return 0;
}

G - Line belt    HDU   3400

给你两个线段AB和CD,在AB上的速度为P,CD上的速度为Q,其他部分为R,求A到D的最小时间。

三分套三分。第一次三分枚举AB上的点,然后第二次枚举CD上的点,然后算出总时间作为比较值。


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#define INF 0x7fffffff
using namespace std;
struct point
{
    double x,y;
}a,b,c,d;
double v1,v2,v0;
double ax,ay,bx,by,cx,cy,dx,dy;
double dis(point a,point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double f(point x)
{
    double t1,t2;
    point l,r,m1,m2;
    l=c,r=d;
    for(int i=0;i<100;i++)
    {
        m1.x=(l.x+r.x)/2;
        m1.y=(l.y+r.y)/2;
        m2.x=(m1.x+r.x)/2;
        m2.y=(m1.y+r.y)/2;
        t1=dis(m1,x)/v0+dis(m1,d)/v2;
        t2=dis(m2,x)/v0+dis(m2,d)/v2;
        if(t1>t2) l=m1;
        else r=m2;
    }
    return t1;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        cin>>a.x>>a.y>>b.x>>b.y>>c.x>>c.y>>d.x>>d.y;
        cin>>v1>>v2>>v0;
        point l,r,m1,m2;
        double t1,t2;
        l=a;r=b;
        for(int i=0;i<100;i++)
        {
            m1.x=(l.x+r.x)/2;
            m1.y=(l.y+r.y)/2;
            m2.x=(m1.x+r.x)/2;
            m2.y=(m1.y+r.y)/2;
            t1=dis(m1,a)/v1+f(m1);
            t2=dis(m2,a)/v1+f(m2);
            if(t1>t2) l=m1;
            else r=m2;
        }
        printf("%.2lf\n",t2);
    }
    return 0;
}



H - The Frog's Games  HDU   4004

经典的最大值最小化问题。

二分枚举最小值,判断是否可行。

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#define INF 0x7fffffff
using namespace std;
int a[1000004];
int main()
{
    int n,m,T,L,i;
    while(scanf("%d%d%d",&L,&n,&m)!=EOF)
    {
        int mx=0;
        for(i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            mx=max(mx,a[i]);
        }
        sort(a,a+n);
        int mn=0;
        for(i=n-1;i>0;i--)
            a[i]-=a[i-1];
        a[n++]=L-mx;
        for(i=0;i<n;i++)
            mn=max(mn,a[i]);
        int mid=0,l=mn,r=L;
        while(l<r)
        {
            mid=(l+r)/2;
            int cnt=0,sum=0;
            for(i=0;i<n;i++)
            {
                if(sum+a[i]<=mid) sum+=a[i];
                else sum=a[i],cnt++;
            }
            if(sum>0) cnt++;
            if(cnt<=m) r=mid;
            else l=mid+1;
        }
        printf("%d\n",l);
    }
    return 0;
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值