码迷,mamicode.com
首页 > 其他好文 > 详细

101170K

时间:2019-10-05 20:01:44      阅读:201      评论:0      收藏:0      [点我收藏+]

标签:精度   ==   space   开始   scanf   画圆   靠谱   极角   tor   

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

神经病这个题真是。
我把浑身本领施展完了开始从题目条件出发,刚想了一下就感觉不太对。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\n",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\n",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\n",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\n");
}

//
//}//

101170K

标签:精度   ==   space   开始   scanf   画圆   靠谱   极角   tor   

原文地址:https://www.cnblogs.com/MXang/p/11625458.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!