lines计算几何
扫除技术提供了对一组几何物体进行排序的方法
动态数据结构
线段端点每遇到一个端点就检查该点是否是相交点
我们简化问题提出两种假设:这在之后证明计算几何的正确性提供了简化
= == = == == = == = = = = == = = == = == = == == = = == == = == = == = = = =
//ccw函数的顺/逆时针的原理
//stl的complex类
计算几何基础:求线段是否相交,特定线段相交
算法导论的实现。
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <algorithm> 5 6 using namespace std; 7 #define maxn 15 8 #define eps 1e-10 9 10 double add(double a,double b) 11 { 12 if(abs(a+b)<eps*(abs(a)+abs(b))) return 0; 13 return a+b; 14 } 15 16 struct node 17 { 18 double x,y; 19 node(){} 20 node(double x,double y):x(x),y(y){} 21 22 node operator +(node p){ //求和 23 return node(add(x,p.x),add(y,p.y)); 24 } 25 26 node operator -(node p){//求差 27 return node(add(x,-p.x),add(y,-p.y)); 28 } 29 30 node operator *(double d){//平行 31 return node(x*d,y*d); 32 } 33 34 double dot(node p){//点积,内积 35 return add(x*p.x,y*p.y); 36 } 37 38 double det(node p){//叉积,外积 39 return add(x*p.y,-y*p.x); 40 } 41 42 }; 43 44 45 46 int direction(node p1,node p2,node p3)//在顺时针或者逆时针方向。 47 { 48 return (p3.operator-(p1)).det((p2.operator-(p1))); 49 } 50 51 52 bool on_segment(node p1,node p2,node p3) 53 {//是否在线段上 54 if((min(p1.x,p2.x)<=p3.x && p3.x<=max(p1.x,p2.x)) && (min(p1.y,p2.y)<=p3.y && p3.y<=max(p1.y,p2.y))) 55 return true; 56 else return false; 57 } 58 59 bool segment_interset(node p1,node q1,node p2,node q2) 60 {//是否相交 61 int d1=direction(p2,q2,p1); 62 int d2=direction(p2,q2,q1); 63 int d3=direction(p1,q1,p2); 64 int d4=direction(p1,q1,q2); 65 66 if(((d1>0 && d2<0)||(d1<0 && d2>0)) && ((d3>0 && d4<0)|| (d3<0 && d4>0))) 67 return true; 68 else if(d1==0 && on_segment(p2,q2,p1)) 69 return true; 70 else if(d2==0 && on_segment(p2,q2,q1)) 71 return true; 72 else if(d3==0 && on_segment(p1,q1,p2)) 73 return true; 74 else if(d4==0 && on_segment(p1,q1,q2)) 75 return true; 76 else return false; 77 } 78 79 80 node p[maxn],q[maxn]; 81 82 int main() 83 {//效率高= = O(1) 84 int n,m; 85 int a,b; 86 scanf("%d",&n); 87 for(int i=0;i<n;i++) 88 scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&q[i].x,&q[i].y); 89 scanf("%d",&m); 90 while(m--) 91 { 92 scanf("%d%d",&a,&b); 93 if(segment_interset(p[a-1],q[a-1],p[b-1],q[b-1])) 94 printf("CONNECTED\n"); 95 else 96 printf("NOT CONNECTED\n"); 97 } 98 return 0; 99 100 }
极限情况考虑,物体撞击。
1.考虑直接撞上猪,然后在撞上的同时,猪上方的障碍物要保证不相撞。在这条路线中途也不能装上其他的障碍物,考虑以这条路径去走的,在走到某个障碍物时考虑与左侧和右侧的相对位置,然后做判断。
2.考虑不直接撞上猪,在飞的过程中以每个障碍物的左上角或者右上角为极限情况考虑然后考虑在这个飞行过程中到达猪x位置时,y是否大于它,且中途不再撞到障碍物。//😢😢😢= =。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 7 using namespace std; 8 9 #define eps 1e-10 10 #define maxn 55 11 12 const double g=9.8; 13 14 int N,V,X,Y; 15 int L[maxn],B[maxn],R[maxn],T[maxn]; 16 17 18 double calc(double vy,double t) 19 { 20 return vy*t-g*t*t/2; 21 } 22 23 int cmp(double lb,double ub,double a) 24 { 25 return a<lb+eps ? -1 : a > ub-eps ? 1:0; 26 } 27 28 bool check(double qx,double qy) 29 { 30 double a=g*g/4,b=g*qy-V*V,c=qx*qx+qy*qy; 31 32 double D=b*b-4*a*c; 33 34 if(D<0 && D>-eps) D=0; 35 if(D<0) return false; 36 37 for(int d=-1;d<=1;d+=2) 38 { 39 double t2=(-b+d*sqrt(D))/(2*a); 40 if(t2<=0) continue; 41 double t=sqrt(t2); 42 43 double vx=qx/t,vy=(qy+g*t*t/2)/t; 44 45 double yt=calc(vy,X/vx); 46 if(yt<Y-eps) continue; 47 48 bool ok=true; 49 for(int i=0;i<N;i++) 50 { 51 if(L[i]>=X) continue; 52 53 if(R[i]==X && Y<=T[i] && B[i]<=yt) ok=false; 54 55 int yL=cmp(B[i],T[i],calc(vy,L[i]/vx)); 56 int yR=cmp(B[i],T[i],calc(vy,R[i]/vx)); 57 int xH=cmp(L[i],R[i],vx*(vy/g)); 58 int yH=cmp(B[i],T[i],calc(vy,vy/g)); 59 if(xH==0 && yH>=0 && yL<0) ok=false; 60 if(yL*yR<=0) ok=false; 61 } 62 if(ok) return true; 63 } 64 return false; 65 } 66 67 void solve() 68 { 69 for(int i=0;i<N;i++) 70 { 71 R[i]=min(R[i],X); 72 } 73 74 bool ok=check(X,Y); 75 for(int i=0;i<N;i++) 76 { 77 ok|=check(L[i],T[i]); 78 ok|=check(R[i],T[i]); 79 } 80 puts(ok?"Yes":"No"); 81 } 82 83 int main() 84 { 85 scanf("%d%d",&N,&V); 86 scanf("%d%d",&X,&Y); 87 88 for(int i=0;i<N;i++) 89 { 90 scanf("%d%d%d%d",&L[i],&B[i],&R[i],&T[i]); 91 } 92 solve(); 93 return 0; 94 }
uva,191
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 6 using namespace std; 7 #define eps 1e-10 8 9 double add(double a,double b) 10 { 11 if(fabs(a+b)<eps*(fabs(a)+fabs(b))) return 0; 12 return a+b; 13 } 14 15 struct node 16 { 17 double x,y; 18 19 node(){} 20 node(double x,double y):x(x),y(y){} 21 22 node operator+(node p){ 23 return node(add(x,p.x),add(y,p.y)); 24 } 25 26 node operator-(node p){ 27 return node(add(x,-p.x),add(y,-p.y)); 28 } 29 30 double dot(node p){ 31 return add(x*p.x,y*p.y); 32 } 33 34 double det(node p){ 35 return add(x*p.y,-y*p.x); 36 } 37 }; 38 39 int direction(node p1,node p2,node p3) 40 { 41 return (p3.operator-(p1)).det(p2.operator-(p1)); 42 } 43 44 bool on_segment(node p1,node p2,node p3) 45 { 46 if((min(p1.x,p2.x)<=p3.x && p3.x<=max(p1.x,p2.x)) && (min(p1.y,p2.y)<=p3.y && p3.y<=max(p1.y,p2.y))) 47 return true; 48 else 49 return false; 50 } 51 52 bool segment_intersect(node p1,node p2,node p3,node p4) 53 { 54 int d1=direction(p3,p4,p1); 55 int d2=direction(p3,p4,p2); 56 int d3=direction(p1,p2,p3); 57 int d4=direction(p1,p2,p4); 58 59 if(((d1>0 && d2<0)||(d1<0 && d2>0)) && ((d3>0 && d4<0) || (d3<0 && d4>0))) 60 return true; 61 else if(d1==0 && on_segment(p3,p4,p1)) 62 return true; 63 else if(d2==0 && on_segment(p3,p4,p2)) 64 return true; 65 else if(d3==0 && on_segment(p1,p2,p3)) 66 return true; 67 else if(d4==0 && on_segment(p1,p2,p4)) 68 return true; 69 else return false; 70 } 71 72 bool isinside(node p1,node p2,node p3) 73 { 74 return (p2.x<=p1.x)&&(p2.y>=p1.y)&&(p3.x>=p1.x)&&(p3.y<=p1.y); 75 } 76 77 int main() 78 {//方法不错,但是一开始可能那个赋值的算法可能有点错误。 79 int n; 80 node a,b,c,d,e,f; 81 while(~scanf("%d",&n)) 82 while(n--) 83 {//考虑精度,lf能很好的保证精度的缺失。 84 scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y); 85 scanf("%lf%lf%lf%lf",&e.x,&e.y,&f.x,&f.y); 86 //很明确的说明了左上角 87 //很明确的说明了右下角。然后建立线段。 88 c=node(min(e.x,f.x),max(e.y,f.y)); 89 d=node(max(e.x,f.x),min(e.y,f.y)); 90 if(segment_intersect(a,b,c,node(c.x,d.y)) || segment_intersect(a,b,node(c.x,d.y),d)|| 91 segment_intersect(a,b,c,node(d.x,c.y)) || segment_intersect(a,b,node(d.x,c.y),d)) 92 { 93 printf("T\n"); 94 } 95 else if(isinside(a,c,d) || isinside(b,c,d)) 96 { 97 printf("T\n"); 98 } 99 else printf("F\n"); 100 } 101 return 0; 102 103 }
uva,11343
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 6 using namespace std; 7 #define eps 1e-10 8 9 double add(double a,double b) 10 { 11 if(fabs(a+b)<eps*(fabs(a)+fabs(b))) return 0; 12 return a+b; 13 } 14 15 struct node 16 { 17 double x,y; 18 19 node(){} 20 node(double x,double y):x(x),y(y){} 21 22 node operator+(node p){ 23 return node(add(x,p.x),add(y,p.y)); 24 } 25 26 node operator-(node p){ 27 return node(add(x,-p.x),add(y,-p.y)); 28 } 29 30 double dot(node p){ 31 return add(x*p.x,y*p.y); 32 } 33 34 double det(node p){ 35 return add(x*p.y,-y*p.x); 36 } 37 }; 38 39 int direction(node p1,node p2,node p3) 40 { 41 return (p3.operator-(p1)).det(p2.operator-(p1)); 42 } 43 44 bool on_segment(node p1,node p2,node p3) 45 { 46 if((min(p1.x,p2.x)<=p3.x && p3.x<=max(p1.x,p2.x)) && (min(p1.y,p2.y)<=p3.y && p3.y<=max(p1.y,p2.y))) 47 return true; 48 else 49 return false; 50 } 51 52 bool segment_intersect(node p1,node p2,node p3,node p4) 53 { 54 int d1=direction(p3,p4,p1); 55 int d2=direction(p3,p4,p2); 56 int d3=direction(p1,p2,p3); 57 int d4=direction(p1,p2,p4); 58 59 if(((d1>0 && d2<0)||(d1<0 && d2>0)) && ((d3>0 && d4<0) || (d3<0 && d4>0))) 60 return true; 61 else if(d1==0 && on_segment(p3,p4,p1)) 62 return true; 63 else if(d2==0 && on_segment(p3,p4,p2)) 64 return true; 65 else if(d3==0 && on_segment(p1,p2,p3)) 66 return true; 67 else if(d4==0 && on_segment(p1,p2,p4)) 68 return true; 69 else return false; 70 } 71 72 73 int main() 74 { 75 node p[105],q[105]; 76 int n,m; 77 scanf("%d",&n); 78 while(n--) 79 { 80 scanf("%d",&m); 81 for(int i=0;i<m;i++) 82 scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&q[i].x,&q[i].y); 83 84 int cnt=0; 85 bool vis[105]; 86 memset(vis,false,sizeof(vis)); 87 for(int i=0;i<m;i++) 88 { 89 for(int j=0;j<m;j++) 90 { 91 if(j!=i) 92 { 93 if(segment_intersect(p[i],q[i],p[j],q[j])) 94 { 95 vis[i]=true; 96 break; 97 } 98 } 99 } 100 } 101 102 for(int i=0;i<m;i++) 103 { 104 if(!vis[i]) 105 cnt++; 106 } 107 printf("%d\n",cnt); 108 109 } 110 return 0; 111 }
uva,378
有时候不需要其他的方法其实你知道的就能做,只是注意精度
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 6 using namespace std; 7 #define eps 1e-10 8 int flag; 9 10 double add(double a,double b) 11 { 12 if(fabs(a+b)<eps*(fabs(a)+fabs(b))) return 0; 13 return a+b; 14 } 15 16 struct node 17 { 18 double x,y; 19 20 node(){} 21 node(double x,double y):x(x),y(y){} 22 23 node operator+(node p){ 24 return node(add(x,p.x),add(y,p.y)); 25 } 26 27 node operator-(node p){ 28 return node(add(x,-p.x),add(y,-p.y)); 29 } 30 31 node operator*(double d){ 32 return node(x*d,y*d); 33 } 34 35 double dot(node p){ 36 return add(x*p.x,y*p.y); 37 } 38 39 double det(node p){ 40 return add(x*p.y,-y*p.x); 41 } 42 }; 43 44 45 bool gx(node a,node b,node c) 46 { 47 return (b.operator-(a)).det(c.operator-(a))==0; 48 } 49 50 node calc(node a,node b,node c,node d) 51 { 52 double A1=d.y-c.y,B1=b.y-a.y,C1=d.x-c.x,D1=b.x-a.x; 53 double A2=(b.operator-(a)).det(d.operator-(c)); 54 double D2=(d.operator-(c)).det(b.operator-(a)); 55 double B2=d.x-b.x,C2=d.y-b.y; 56 57 double x=(C1*D1*C2+B1*C1*b.x-(A1*D1*d.x))/D2; 58 double y=(B1*A1*B2+D1*A1*b.y-(C1*B1*d.y))/A2; 59 60 return node(x,y); 61 } 62 int main() 63 { 64 int n; 65 node a,b,c,d; 66 scanf("%d",&n); 67 puts("INTERSECTING LINES OUTPUT"); 68 while(n--) 69 { 70 scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y,&d.x,&d.y); 71 if((d.y-c.y)*(b.x-a.x)==(d.x-c.x)*(b.y-a.y)) 72 { 73 if(gx(a,b,c)) 74 printf("LINE\n"); 75 else printf("NONE\n"); 76 } 77 else 78 printf("POINT %.2lf %.2lf\n",calc(a,b,c,d).x,calc(a,b,c,d).y); 79 } 80 puts("END OF OUTPUT"); 81 }
uva,10902
注意到n很大了,如果用每次输入就与前面的所有数比较为O(n*n)的复杂度,肯定超时了。
因为有最上面的管子不会超过1000个这个可以枚举,而且从逆向来看的话又能大大削减复杂度,最后弄一个二分查找,时间复杂度O(n*logn)最坏,有些情况下可能找很少的管子就可以了。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 6 using namespace std; 7 #define eps 1e-10 8 #define maxn 100005 9 10 double add(double a,double b) 11 { 12 if(fabs(a+b)<eps*(fabs(a)+fabs(b))) return 0; 13 return a+b; 14 } 15 16 struct node 17 { 18 double x,y; 19 int state; 20 21 node(){} 22 node(double x,double y):x(x),y(y){} 23 24 node operator+(node p){ 25 return node(add(x,p.x),add(y,p.y)); 26 } 27 28 node operator-(node p){ 29 return node(add(x,-p.x),add(y,-p.y)); 30 } 31 32 double dot(node p){ 33 return add(x*p.x,y*p.y); 34 } 35 36 double det(node p){ 37 return add(x*p.y,-y*p.x); 38 } 39 }; 40 41 int direction(node p1,node p2,node p3) 42 { 43 return (p3.operator-(p1)).det(p2.operator-(p1)); 44 } 45 46 bool on_segment(node p1,node p2,node p3) 47 { 48 if((min(p1.x,p2.x)<=p3.x && p3.x<=max(p1.x,p2.x)) && (min(p1.y,p2.y)<=p3.y && p3.y<=max(p1.y,p2.y))) 49 return true; 50 else 51 return false; 52 } 53 54 bool segment_intersect(node p1,node p2,node p3,node p4) 55 { 56 int d1=direction(p3,p4,p1); 57 int d2=direction(p3,p4,p2); 58 int d3=direction(p1,p2,p3); 59 int d4=direction(p1,p2,p4); 60 61 if(((d1>0 && d2<0)||(d1<0 && d2>0)) && ((d3>0 && d4<0) || (d3<0 && d4>0))) 62 return true; 63 else if(d1==0 && on_segment(p3,p4,p1)) 64 return true; 65 else if(d2==0 && on_segment(p3,p4,p2)) 66 return true; 67 else if(d3==0 && on_segment(p1,p2,p3)) 68 return true; 69 else if(d4==0 && on_segment(p1,p2,p4)) 70 return true; 71 else return false; 72 } 73 node p[maxn],q[maxn]; 74 int flag1; 75 76 void find(int s,int l,int r) 77 { 78 if(l>=r || flag1) return; 79 if(segment_intersect(p[s],q[s],p[l],q[l]) || segment_intersect(p[s],q[s],p[r],q[r])) 80 flag1=1; 81 find(s,l,(l+r)/2); 82 find(s,((l+r)/2)+1,r); 83 } 84 85 int main() 86 { 87 int n; 88 while(scanf("%d",&n),n) 89 { 90 int cnt=1; 91 for(int i=0;i<n;i++) 92 { 93 p[i].state=q[i].state=1; 94 scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&q[i].x,&q[i].y); 95 } 96 97 for(int i=n-2;i>=0 && cnt<=1000;i--) 98 { 99 flag1=0; 100 find(i,i+1,n-1); 101 if(segment_intersect(p[i],q[i],p[n-1],q[n-1])) 102 flag1=1; 103 if(flag1) 104 p[i].state=0; 105 else cnt++; 106 } 107 int flag=0; 108 printf("Top sticks:"); 109 for(int i=0;i<n;i++) 110 if(p[i].state) 111 { 112 if(!flag) 113 { 114 printf(" %d",i+1); 115 flag=1; 116 } 117 else 118 { 119 printf(", %d",i+1); 120 } 121 } 122 printf(".\n"); 123 } 124 return 0; 125 }
活在现实,做在梦里。

浙公网安备 33010602011771号