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

    xiaoxiao2021-03-26  22

    成吨的细节。。。

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

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

    那如何判断哪个最优呢?

    我是分类讨论

    设上一个点是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; }

    转载请注明原文地址: https://ju.6miu.com/read-658889.html

    最新回复(0)