卷包裹,线段相交,计算几何(找边界,LA 3218)

来源:互联网 发布:绝食知乎 编辑:程序博客网 时间:2024/05/17 06:58

成吨的细节。。。


就是找右转得最厉害的线段,然后沿着这个线段跑到最近的路口。


那如何找右转得最厉害的线段呢?就是枚举所有可能的下一个点,然后取其中最优的那个即可。

那如何判断哪个最优呢?


我是分类讨论

设上一个点是LAST,这一个点是NOW。

那么我目前的朝向就是V=NOW-LAST。

设两个点A,B。

如果A,B分别是左转和右转,那就选B。

否则如果A扭头,我就选B。

否则如果B扭头,我就选A。

否则如果B相对A右转,我就选B。

否则我选A。


那如何找最近的路口呢?就是枚举路上的所有路口,然后取其中最近的那个即可。

那如何判断最近呢?

直接两点间距离公式即可。


主要是难在很多琐碎的细节需要讨论清楚,否则就会找错方向和路口,从而出错或者陷入死循环。

debug浪费了非常多的时间,如果能完全想清楚再下手写代码就好了。

就是仅仅有大致思路是不够的,尽量把实现的细节都完全弄明白,具体到这个功能块每一步该怎么做,可以拿张纸写下具体过程,然后证明正确了再动手写代码。否则等到你写的时候就会比较无暇顾及细节,容易出错,而且没有那种对程序精细的掌控感。一旦出bug的话就会很不知所措,只能慢吞吞地单步调试。


再次通过自己带数据查出bug。这个方法真的很强.。但是这毕竟治标不治本。这方法不但速度有点慢,而且还得看运气。想办法提升自己的代码AC率才是提升自己的根本方法。既要学会使用技巧也要想办法提升自己。


代码

#include<bits/stdc++.h>using namespace std;struct Point{    double x,y;    Point(double x=0,double y=0):x(x),y(y){}    void Read()    {        scanf("%lf %lf",&x,&y);    }    bool operator < (const Point& rhs) const    {        return x<rhs.x||(x==rhs.x&&y<rhs.y);    }};typedef Point Vector;const double eps = 1e-10;int dcmp(double x){    if(fabs(x)<eps) return 0;    return x<0?-1:1;}Point operator + (Point A,Vector B){    return Point(A.x+B.x,A.y+B.y);}Vector operator - (Point A,Point B){    return Vector(A.x-B.x,A.y-B.y);}Vector operator * (Vector V,double t){    return Vector(V.x*t,V.y*t);}bool operator == (Point A,Point B){    return dcmp(A.x-B.x)==0&&dcmp(A.y-B.y)==0;}bool operator != (Point A,Point B){    return dcmp(A.x-B.x)!=0||dcmp(A.y-B.y)!=0;}double Dot(Vector A,Vector B){    return A.x*B.x+A.y*B.y;}double Cross(Vector A,Vector B){    return A.x*B.y-A.y*B.x;}double Len(Vector V){    return sqrt(Dot(V,V));}double Dist(Point A,Point B){    return Len(A-B);}Point GetIntersection(Point A,Point B,Point C,Point D){    Vector V1=B-A;    Vector V2=D-C;    Vector V3=C-A;    double t=Cross(V3,V2)/Cross(V1,V2);    return A+V1*t;}bool OnSegment(Point P,Point A,Point B){    Vector V1=A-P;    Vector V2=B-P;    return dcmp(Len(V1))==0||dcmp(Len(V2))==0||(dcmp(Cross(V1,V2))==0&&dcmp(Dot(V1,V2))<0);}bool SegmentIntersection(Point A,Point B,Point C,Point D){    if(dcmp(Cross(B-A,D-C))==0) return false;    if(OnSegment(A,C,D)||OnSegment(B,C,D)||OnSegment(C,A,B)||OnSegment(D,A,B)) return true;    Vector V1=C-A;    Vector V2=D-A;    Vector V3=A-C;    Vector V4=B-C;    return dcmp(Cross(B-A,V1))*dcmp(Cross(B-A,V2))<0&&dcmp(Cross(D-C,V3))*dcmp(Cross(D-C,V4))<0;}const int maxn = 110;int n;Point P[maxn];Point Poly[maxn*maxn];int cnt;Point s;Point last,now;bool cmp1(Point A,Point B){    return dcmp(Dist(last,A)-Dist(last,B))>0;}bool cmp2(Point A,Point B){    Vector V1=A-now;    Vector V2=B-now;    Vector V3=now-last;    if(dcmp(Cross(V3,V1))*dcmp(Cross(V3,V2))<0) return dcmp(Cross(V3,V2))<0;    else if(dcmp(Cross(V3,V2))==0&&dcmp(Dot(V3,V2))<0) return false;    else if(dcmp(Cross(V3,V1))==0&&dcmp(Dot(V3,V1))<0) return true;    return dcmp(Cross(V1,V2))<=0;}int main(){    while(~scanf("%d",&n))    {        s=Point(200,200);        for(int i=0;i<n;i++)        {            P[i].Read();            if(P[i]<s) s=P[i];        }        last=s;        last.x-=10;        now=s;        Point Next;        cnt=0;        while(1)        {            Poly[cnt++]=now;            bool you=false;            for(int i=0;i<n;i++)                if(OnSegment(now,P[i],P[(i+1)%n]))                {                    if(!OnSegment(P[i],now,last)&&(!you||cmp2(Next,P[i]))) Next=P[i],you=true;                    if(!OnSegment(P[(i+1)%n],now,last)&&(!you||cmp2(Next,P[(i+1)%n]))) Next=P[(i+1)%n],you=true;                }            for(int i=0;i<n;i++)                if(SegmentIntersection(now,Next,P[i],P[(i+1)%n]))                {                    Point Temp=GetIntersection(now,Next,P[i],P[(i+1)%n]);                    if(Temp!=now) Next=Temp;                }            if(Next==s) break;            last=now;            now=Next;        }        printf("%d\n",cnt);        for(int i=0;i<cnt;i++)            printf("%lf %lf\n",Poly[i].x,Poly[i].y);    }    return 0;}


0 0