This article is made by Jason-Cow.
Welcome to reprint.
But please post the article's address.
核心思想
1.积角排序
2.双端队列维护半平面交
木有啦~~
1 int HPI(L*l,int n,D*ans){ 2 int head,tail,m=0;D*P=new D[n];L*q=new L[n]; 3 sort(l+1,l+n+1),q[head=tail=0]=l[1]; 4 for(int i=2;i<=n;i++){ 5 while(head<tail && !Left(l[i],P[tail-1]))tail--; 6 while(head<tail && !Left(l[i],P[head])) head++; 7 q[++tail]=l[i];//双端队列<( ̄3 ̄)> 8 if(fabs(Cross(q[tail].v,q[tail-1].v))<eps){ 9 tail--;//判断Cross(q[tail].v,q[tail-1].v)==0♪(^∇^*) 10 if(Left(q[tail],l[i].P))q[tail]=l[i]; 11 } 12 if(head<tail)P[tail-1]=Intersect(q[tail-1],q[tail]); 13 } 14 while(head<tail && !Left(q[head],P[tail-1]))tail--; 15 if(tail-head<=1)return 0; 16 P[tail]=Intersect(q[tail],q[head]); 17 for(int i=head;i<=tail;i++)ans[++m]=P[i]; 18 return m; 19 }
多边形相关
db Area(D*R,int n){ db S=0.0; for(int i=1;i<n;i++)S+=Cross(R[i]-R[1],R[i+1]-R[1]); return S/2; } db Length(D*R,int n){ db C=0.0; for(int i=2;i<=n;i++)C+=Dis(R[i],R[i-1]); return C+Dis(R[n],R[1]); }
主程序
1 L l[500];D A[500]; 2 int main(){ 3 for(int n;scanf("%d",&n)&&n;){ 4 for(int i=1;i<=n;i++){ 5 db a,b,c,d; 6 scanf("%lf%lf%lf%lf",&a,&b,&c,&d); 7 D A(a,b),B(c,d); 8 l[i]=L(A,B-A); 9 } 10 int m=HPI(l,n,A); 11 cout<<"m="<<m<<endl; 12 for(int i=1;i<=m;i++)printf("(%.4lf,%.4lf)\n",A[i].x,A[i].y); 13 printf("S=%.2lf\n",Area(A,m)); 14 printf("C=%.2lf\n",Length(A,m)); 15 } 16 return 0; 17 }
读入,如图(橙、红、蓝、绿)
4
2 1 1 2
1 2 0 1
1 0 2 1
0 1 1 0
输出
m=4
(0.0000,1.0000)
(1.0000,0.0000)
(2.0000,1.0000)
(1.0000,2.0000)
S=2.00
C=5.66
读入
6
1 2 0 1
0 1.8 0.8 0.2
0 1 1 0
1 0 2 1
3 0 1 2
0.6 1.6 0 0.7
输出
m=6
(0.6000,1.6000)
(0.3143,1.1714)
(0.8000,0.2000)
(1.0000,0.0000)
(2.0000,1.0000)
(1.0000,2.0000)
S=1.76
C=5.28
完整代码
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <vector> 7 #include <cmath> 8 #include <queue> 9 #include <map> 10 #include <set> 11 using namespace std; 12 #define sqr(x) ((x)*(x)) 13 #define RG register 14 #define op operator 15 #define IL inline 16 typedef double db; 17 typedef bool bl; 18 const db pi=acos(-1.0),eps=1e-10; 19 struct D{ 20 db x,y; 21 D(db x=0.0,db y=0.0):x(x),y(y){} 22 }; 23 typedef D V;//不知道什么鬼,emacs 将 operator -> op 会萎掉 对!不!齐! 24 bl operator<(D A,D B){return A.x<B.x||(A.x==B.x&&A.y<B.y);} 25 V operator+(V A,V B){return V(A.x+B.x,A.y+B.y);} 26 V operator-(V A,V B){return V(A.x-B.x,A.y-B.y);} 27 V operator*(V A,db N){return V(A.x*N,A.y*N);} 28 V operator/(V A,db N){return V(A.x/N,A.y/N);} 29 30 db Ang(db x){return(x*180.0/pi);} 31 db Rad(db x){return(x*pi/180.0);} 32 V Rotate(V A,db a){return V(A.x*cos(a)-A.y*sin(a),A.x*sin(a)+A.y*cos(a));} 33 db Dis(D A,D B){return sqrt(sqr(A.x-B.x)+sqr(A.y-B.y));} 34 db Cross(V A,V B){return A.x*B.y-A.y*B.x;} 35 36 db Area(D*R,int n){ 37 db S=0.0; 38 for(int i=1;i<n;i++)S+=Cross(R[i]-R[1],R[i+1]-R[1]); 39 return S/2; 40 } 41 42 db Length(D*R,int n){ 43 db C=0.0; 44 for(int i=2;i<=n;i++)C+=Dis(R[i],R[i-1]); 45 return C+Dis(R[n],R[1]); 46 } 47 48 struct L{ 49 D P,v; 50 db a; 51 L(){} 52 L(D P,V v):P(P),v(v){a=atan2(v.y,v.x);} 53 bool operator<(const L x)const{return a<x.a;} 54 }; 55 56 D Intersect(L a,L b){ 57 V u=a.P-b.P; 58 return a.P+a.v*(Cross(b.v,u)/Cross(a.v,b.v)); 59 } 60 61 bool Left(L l,D A){ 62 return Cross(l.v,A-l.P)>0; 63 } 64 65 int HPI(L*l,int n,D*ans){ 66 int head,tail,m=0;D*P=new D[n];L*q=new L[n]; 67 sort(l+1,l+n+1),q[head=tail=0]=l[1]; 68 for(int i=2;i<=n;i++){ 69 while(head<tail && !Left(l[i],P[tail-1]))tail--; 70 while(head<tail && !Left(l[i],P[head])) head++; 71 q[++tail]=l[i];//双端队列<( ̄3 ̄)> 72 if(fabs(Cross(q[tail].v,q[tail-1].v))<eps){ 73 tail--;//判断Cross(q[tail].v,q[tail-1].v)==0♪(^∇^*) 74 if(Left(q[tail],l[i].P))q[tail]=l[i]; 75 } 76 if(head<tail)P[tail-1]=Intersect(q[tail-1],q[tail]); 77 } 78 while(head<tail && !Left(q[head],P[tail-1]))tail--; 79 if(tail-head<=1)return 0; 80 P[tail]=Intersect(q[tail],q[head]); 81 for(int i=head;i<=tail;i++)ans[++m]=P[i]; 82 return m; 83 } 84 85 L l[500]; 86 D A[500]; 87 int main(){ 88 cout<<4*sqrt(2)<<endl; 89 for(int n;scanf("%d",&n)&&n;){ 90 for(int i=1;i<=n;i++){ 91 db a,b,c,d; 92 scanf("%lf%lf%lf%lf",&a,&b,&c,&d); 93 D A(a,b),B(c,d); 94 l[i]=L(A,B-A); 95 } 96 int m=HPI(l,n,A); 97 cout<<"m="<<m<<endl;for(int i=1;i<=m;i++)printf("(%.4lf,%.4lf)\n",A[i].x,A[i].y); 98 printf("S=%.2lf\n",Area(A,m)); 99 printf("C=%.2lf\n",Length(A,m)); 100 } 101 return 0; 102 }