zoukankan      html  css  js  c++  java
  • P4385 [COCI2009]Dvapravca

    首先特判掉蓝点数量(<2)的情况。没有蓝点答案就是(n),有一个蓝点可以枚举一个红点,选择过这个蓝点和红点的一条线和在无穷远处的平行线(即这条线对应的两个半平面)。

    这里认为过一个点是与这个点无限接近,红点的话认为红点在平行线中,蓝点不在平行线中

    构造方案的时候想象两个阶段:

    • 如果有一条线不过蓝点,可以继续向外扩张直到过蓝点为止,现在两条平行线固定过两个蓝点
    • 如果没有平行线过红点,可以旋转这两条平行线知道一个平行线过红点为止。这个过程不会损失红点,而且可能加入新的红点。

    所以结论是:两条平行线肯定分别过两个蓝点,而且还有一条平行线过一个红点。

    先枚举一个蓝点和一个红点,一条线过这两个点;然后找到在两个方向距离这条线最近的蓝点,直接算红点数量即可。

    复杂度(O(n^3))

    直接做肯定过不去,所以先把整张图随机旋转,然后按照x坐标排序。

    时间的正确性请咨询@Leo______ 。

    #include<bits/stdc++.h>
    #define il inline
    #define vd void
    il int gi(){
        int x=0,f=0;char ch=getchar();
        while(!isdigit(ch))f^=ch=='-',ch=getchar();
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return f?-x:x;
    }
    struct point{double x,y;}r[1010],b[1010];
    il bool operator<(const point&a,const point&b){return a.x<b.x;}
    char col;
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("in.in","r",stdin);
        freopen("out.out","w",stdout);
    #endif
        int n=gi(),R=0,B=0;
        srand(time(NULL));
        double v=rand()%1000*0.1+0.1;
        for(int i=1;i<=n;++i){
            int _x=gi(),_y=gi();
            do col=getchar();while(col!='R'&&col!='B');
            if(col=='R')r[++R]=(point){sin(v)*_x-cos(v)*_y,sin(v)*_y-cos(v)*_x};
            else b[++B]=(point){sin(v)*_x-cos(v)*_y,sin(v)*_y-cos(v)*_x};
        }
        std::sort(r+1,r+R+1);
        std::sort(b+1,b+B+1);
        if(!B)return printf("%d
    ",n),0;
        int ans=0;
        double kk,bb,dist,dist_up,dist_dn;
        int upans,dnans;
        for(int i=1;i<=B;++i)
            for(int j=1;j<=R;++j){
                kk=1.0*(b[i].y-r[j].y)/(b[i].x-r[j].x),bb=b[i].y-kk*b[i].x;
                dist_up=1e18,dist_dn=1e18;
                for(int k=1;k<=B;++k)
                    if(k!=i){
                        dist=kk*b[k].x+bb-b[k].y;
                        if(dist<0){
                            if(-dist<dist_up)dist_up=-dist;
                        }else{
                            if(dist<dist_dn)dist_dn=dist;
                        }
                    }
                upans=1,dnans=1;
                for(int k=1;k<=R;++k)
                    if(k!=j){
                        dist=kk*r[k].x+bb-r[k].y;
                        if(dist<0){
                            if(-dist<=dist_up+1e-7)++upans;
                        }else{
                            if(dist<=dist_dn+1e-7)++dnans;
                        }
                    }
                ans=std::max(ans,std::max(upans,dnans));
            }
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    Python 学习日记 第七天
    Python 学习日记 第六天
    Python 学习日记 第五天
    Python 学习日记 第四天
    Redis 中的数据类型及基本操作
    Asp.net mvc 中View 的呈现(二)
    Asp.net mvc 中View的呈现(一)
    Asp.net mvc 中Action 方法的执行(三)
    Asp.net mvc 中Action 方法的执行(二)
    Asp.net mvc 中Action 方法的执行(一)
  • 原文地址:https://www.cnblogs.com/xzz_233/p/10234276.html
Copyright © 2011-2022 走看看