POJ 3384 Feng Shui

坑爹的题,,就是先向内推进r,然后半平面交得出圆心范围。

然后旋转卡壳求最远点对

这道题首先样例给的就不对,不知道什么情况

然后一直WA,后来看了discuss,试了下这组数据:

4 1
0 0
0 2
2 2
2 0

发现n个端点两两距离都一样时会出错,然后改了改代码,就A了

总结就是一直WA的时候,一定要学会看discuss

#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
const double eps=1e-5;
struct Point {
    double x,y;
    Point (){}
    Point (double xx,double yy) {x=xx;y=yy;}
    Point operator -(const Point b)const {return Point(x-b.x,y-b.y);}
    double operator ^(const Point b)const {return x*b.y-y*b.x;}
};
struct Line {
    Point s,e;
    double angle;
    Line(){}
    Line(Point ss,Point ee) {s=ss;e=ee;}
    Point operator &(const Line b)const {
        Point res=s;
        double t=((s-b.e)^(b.s-b.e))/((s-e)^(b.s-b.e));
        res.x+=(e.x-s.x)*t;
        res.y+=(e.y-s.y)*t;
        return res;
    }
};
int n,m;
int r;
Point p[105];
Line l[105],dq[105];
int cmp(Line a,Line b) {
    if (fabs(a.angle-b.angle)<eps) return ((a.e-a.s)^(b.s-a.s))>eps;
    else return a.angle<b.angle;
}
double dist(Point a,Point b) {
    return sqrt((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y));
}
void HPI(){
    sort(l,l+n,cmp);
    int ln;
    for(int i=1,j=0;i<n;i++){
        if (l[i].angle-l[j].angle>eps) l[++j]=l[i];
        ln=j+1;
    }
    dq[0]=l[0];dq[1]=l[1];
    int bot=0,top=1;
    //for(int i=0;i<ln;i++) printf("%f %f\n",l[i].s.x,l[i].s.y);
    for(int i=2;i<ln;i++) {
        while (bot<top && ((l[i].e-l[i].s)^((dq[top]&dq[top-1])-l[i].s))>eps) top--;
        while (bot<top && ((l[i].e-l[i].s)^((dq[bot]&dq[bot+1])-l[i].s))>eps) bot++;
        dq[++top]=l[i];
    }
    while (bot<top && ((dq[bot].e-dq[bot].s)^((dq[top]&dq[top-1])-dq[bot].s))>eps) top--;
    while (bot<top && ((dq[top].e-dq[top].s)^((dq[bot]&dq[bot+1])-dq[top].s))>eps) bot++;
    //for(int i=bot;i<top;i++) printf("%lf %lf\n",dq[i].s.x,dq[i].s.y);
    if (top<=bot+1) return;
    dq[++top]=dq[bot];
    m=0;
    for(int i=bot;i<top;i++){
        p[m++]=dq[i]&dq[i+1];
        //printf("%lf %lf\n",p[m-1].x,p[m-1].y);
    }
    //方便处理
    p[m]=p[0];
}
int main() {
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif // ONLINE_JUDGE
    while(scanf("%d%d",&n,&r)!=EOF) {
        for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);


        p[n]=p[0];
        for(int i=0;i<n;i++) {
            //向内推进r
            double dx,dy,len;
            Point ta,tb;
            ta=p[i];tb=p[i+1];
            dx=p[i+1].y-p[i].y;
            dy=p[i].x-p[i+1].x;
            len=sqrt(dx*dx+dy*dy);
            ta.x=p[i].x+dx*r/len;
            ta.y=p[i].y+dy*r/len;
            tb.x=p[i+1].x+dx*r/len;
            tb.y=p[i+1].y+dy*r/len;
            l[i].s=ta;
            l[i].e=tb;
            l[i].angle=atan2(tb.y-ta.y,tb.x-ta.x);
            //printf("%f %f\n",l[i].s.x,l[i].s.y);
        }
        HPI();
        //旋转卡壳求最远点对,点逆时针排列
        double ans=0;
        Point a,b;
        //printf("%d\n",m);
        for(int i=0,j=1;i<m;i++) {
            while(((p[i+1]-p[i])^(p[j]-p[i]))<((p[i+1]-p[i])^(p[j+1]-p[i]))) j=(j+1)%m;
            //printf("%f \n",((p[i+1]-p[i])^(p[j]-p[i])));
            //printf("%f %f\n",p[i].x,p[i].y);
            if (dist(p[i],p[j])>=ans) {
                a=p[i];b=p[j];
                ans=dist(p[i],p[j]);
            }
            if (dist(p[i+1],p[j+1])>=ans) {
                a=p[i+1];b=p[j+1];
                ans=dist(p[i+1],p[j+1]);
            }
        }
        printf("%.4f %.4f %.4f %.4f\n",a.x,a.y,b.x,b.y);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值