• 101170K


    “我真难,真的,”mxy抬起他没有神采的眼睛来,接着说。“我单知道半平面交可以往凸包里放圆,放两个一样的就找最远的一对端点;我不知道凹多边形就会死掉。我一个多小时就开了K题,感觉和poj风水是一个题,就粘了份半平面交板子。板子很靠谱的,遇见的题都能过;交上去wa1。我就继续改精度,交上去,又wa1了,要重新读遍题。我读完题,感觉没有错,去网上找了份新板子,只见又wa1了,没有生命迹象了。我是不是想的太简单了;画了几张图,果然出现了恐怖的事情。我急了,在那挠头发,过了好半会儿,想到了jls18年出的多校,也是凹多边形往里塞圆的。我觉得稳了,必过,再不过我吃屎。再提交;竟然tle了,想了半天,原来那道题的复杂度是O(n³)的。……” 他接着但是呜咽,说不出成句的话来。

    神经病这个题真是。
    我把浑身本领施展完了开始从题目条件出发,刚想了一下就感觉不太对。30m????
    这树才4米啊???
    『当时和队友得出的结论是,凹多边形一定有解,凸包的话用我原来的缩边半平面交就行』
    上面的结论显然是对的,问题在于如何找凹多边形的解。
    想到的是『找到一个凹点两侧的凸点,角平分线画圆即可』。
    可惜的是时间不够调试了,没过。

    赛后看qls代码发现了更巧妙的做法。看所有的凸点是否可行然后找一对可行的即可。(其实本质上差不多?)

    补完看题解。四个点及以上一定有解。wslndmnmntys

    从头被治到尾,太治傻逼了。
    主要是题目给人的感觉太熟悉了,,很容易就想到半平面交和jls的那个多边形放圆了,都试完了才回头挖掘题目所给的条件,可惜时间来不及了。

    #include <bits/stdc++.h>
    using namespace std;
    typedef double db;
    const db eps=1e-6;
    const db R = 4000.0;
    int sign(db k){
        if (k>eps) return 1; else if (k<-eps) return -1; return 0;
    }
    int cmp(db k1,db k2){return sign(k1-k2);}
    int inmid(db k1,db k2,db k3){return sign(k1-k3)*sign(k2-k3)<=0;}// k3 在 [k1,k2] 内
    struct point{
        db x,y;
        point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
        point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
        point operator * (db k1) const{return (point){x*k1,y*k1};}
        point operator / (db k1) const{return (point){x/k1,y/k1};}
        int operator == (const point &k1) const{return cmp(x,k1.x)==0&&cmp(y,k1.y)==0;}
        // 逆时针旋转
        point turn(db k1){return (point){x*cos(k1)-y*sin(k1),x*sin(k1)+y*cos(k1)};}
        point turn90(){return (point){-y,x};}
        bool operator < (const point k1) const{
            int a=cmp(x,k1.x);
            if (a==-1) return 1; else if (a==1) return 0; else return cmp(y,k1.y)==-1;
        }
        db abs(){return sqrt(x*x+y*y);}
        db abs2(){return x*x+y*y;}
        db dis(point k1){return ((*this)-k1).abs();}
        point unit(){db w=abs(); return (point){x/w,y/w};}
        void scan(){double k1,k2; scanf("%lf%lf",&k1,&k2); x=k1; y=k2;}
        void print(){printf("%.8lf %.8lf
    ",x,y);}
        db getw(){return atan2(y,x);}
        point getdel(){if (sign(x)==-1||(sign(x)==0&&sign(y)==-1)) return (*this)*(-1); else return (*this);}
        int getP() const{return sign(y)==1||(sign(y)==0&&sign(x)==-1);}
    };
    int inmid(point k1,point k2,point k3){return inmid(k1.x,k2.x,k3.x)&&inmid(k1.y,k2.y,k3.y);}
    db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
    db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;}
    db rad(point k1,point k2){return atan2(cross(k1,k2),dot(k1,k2));}
    // -pi -> pi
    int compareangle (point k1,point k2){//极角排序+
        return k1.getP()<k2.getP()||(k1.getP()==k2.getP()&&sign(cross(k1,k2))>0);
    }
    point proj(point k1,point k2,point q){ // q 到直线 k1,k2 的投影
        point k=k2-k1;return k1+k*(dot(q-k1,k)/k.abs2());
    }
    point reflect(point k1,point k2,point q){return proj(k1,k2,q)*2-q;}
    int clockwise(point k1,point k2,point k3){// k1 k2 k3 逆时针 1 顺时针 -1 否则 0
        return sign(cross(k2-k1,k3-k1));
    }
    int checkLL(point k1,point k2,point k3,point k4){// 求直线 (L) 线段 (S)k1,k2 和 k3,k4 的交点
        return cmp(cross(k3-k1,k4-k1),cross(k3-k2,k4-k2))!=0;
    }
    point getLL(point k1,point k2,point k3,point k4){
        db w1=cross(k1-k3,k4-k3),w2=cross(k4-k3,k2-k3); return (k1*w2+k2*w1)/(w1+w2);
    }
    db disSP(point k1,point k2,point q){
        point k3=proj(k1,k2,q);
        if (inmid(k1,k2,k3)) return q.dis(k3); else return min(q.dis(k1),q.dis(k2));
    }
    int n,can[2551];
    point p[2551],ans[2551];
    bool init(int id){
        point y=p[id],x=p[(id-1+n)%n],z=p[(id+1)%n];
        if(cross(z-y,y-x)>0)return false;
        db j = abs(rad(z-y,x-y));
        db dis = R/sin(j/2);
        ans[id] = (((z-y).unit()+(x-y).unit())/2).unit()*dis+y;
    //    x.print();y.print();z.print();ans[id].print();
        for(int i=0;i<n;i++) {
    //        printf("%.11f
    ",disSP(p[i], p[(i + 1) % n], ans[id]));
            if (disSP(p[i], p[(i + 1) % n], ans[id]) < R-eps)
                return false;
        }
        return true;
    }
    int main() {
        scanf("%d", &n);
        for (int i = 0; i < n; i++)scanf("%lf%lf", &p[i].x, &p[i].y);
        reverse(p, p + n);
    //    can[0]=init(0);
        for(int i=0;i<n;i++)can[i]=init(i);//printf("%d
    ",can[i]);
        for(int i=0;i<n;i++)
            if(can[i])
                for(int j=i+1;j<n;j++)
                    if(can[j])
                        if(ans[i].dis(ans[j])>=R*2-eps){
                            ans[i].print();
                            ans[j].print();
                            exit(0);
                        }
        printf("impossible
    ");
    }
    
    //
    //}//
    
  • 相关阅读:
    【转】《基于MFC的OpenGL编程》Part 5 Transformations Rotations, Translations and Scaling
    【转】 《基于MFC的OpenGL编程》Part 10 Texture Mapping
    【转】 《基于MFC的OpenGL编程》Part 11 Blending, Antialiasing and Fog
    win form 托盘功能的实现(引用CSDN)
    C# win form退出窗体时对话框实用
    智能DNS 笔记
    iis无法启动, 找出占用80端口的罪魁祸首
    gvim for windows的剪贴板操作
    内容交换
    Content Networking 读书笔记
  • 原文地址:https://www.cnblogs.com/MXang/p/11625458.html
Copyright © 2020-2023  润新知